Check Twitter Follow Relationship API
Return the directional relationship between a source and target user: whether source follows target (following) and target follows source (followed_by), plus block, mute, and DM-eligibility flags. An account that does not exist returns a 404 with error not_found; the relationship object is null when X returns none. Cost: $0.0008 per call.
Check Follow Relationship returns the directional relationship between a source and target user: whether source follows target and target follows source, plus block, mute, and DM-eligibility flags. Pass each account as a numeric user ID or a username; an account that does not exist returns a 404 with error not_found, and nothing is billed. It is a single $0.0008 read.
Authorization
bearerAuth Pass your API key as a bearer token on every request: Authorization: Bearer <API_KEY>.
In: header
Query Parameters
Numeric ID of the account whose following is checked. Send this or source_username.
Handle of the source account, as an alternative to source_user_id. Resolved to its ID first; an unknown handle returns a 404 and nothing is billed.
Numeric ID of the account being checked against. Send this or target_username.
Handle of the target account, as an alternative to target_user_id. Resolved to its ID first; an unknown handle returns a 404 and nothing is billed.
Comma-separated list of dotted field paths to keep in the response (one parameter, never repeated), applied to every object in the returned lists and to nested objects (for example fields=id,text,author.username; the list's own name may prefix a path, fields=tweets.id). A path prefix that lands on an array applies to each element (media.media_url_https). Pagination and envelope keys (next_cursor, cursor, has_more, count, partial, error, message, reason) are always kept. Unknown paths are ignored; up to 50 paths of up to 6 segments. Projection never changes status codes or billing, and applies to data reads only: account, feedback, session status, monitor (other than deliveries), webhook and stream-compat reads return their bodies unchanged.
Set to 1 (or true) to apply the built-in compact preset: ids, url, text, created_at, lang, the engagement counts, the is_retweet/is_reply/is_quote flags, conversation ids, the author's id/username/name/followers_count/verification, and the quoted or retweeted tweet's id/url/author username. The preset trims what it recognises and leaves alone what it would empty, so it never turns a body into {}. Combine with fields to add paths on top of the preset. Typically cuts a tweet page by 70 to 90 percent for LLM tool callers.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
application/json
curl -X GET "https://example.com/user/check_follow_relationship?source_user_id=745273&source_username=naval&target_user_id=2178758961&target_username=openai&fields=id%2Ctext%2Ccreated_at%2Cauthor.username&compact=1"{ "relationship": { "source_id": "745273", "target_id": "2178758961", "following": true, "followed_by": false, "blocking": null, "blocked_by": null, "muting": null, "can_dm": true }}{ "error": "bad_request", "message": "Missing or malformed parameter. Fix the request before retrying."}{ "error": "unauthorized", "message": "The API key is missing, malformed, or revoked. Check the Authorization header."}{ "error": "insufficient_credits", "message": "Your balance is exhausted. Top up your credits to continue.", "top_up_url": "https://www.twitterapis.com/dashboard/buy-credits?utm_source=api&utm_medium=402"}{ "error": "forbidden", "message": "X refused this resource for the acting account: on a read, the account is not a participant in the DM thread, the target is protected or has blocked it, or the session was attestation-blocked for calling from a datacenter or rotating IP; on a write, the account is not authorized for the action or has no logged-in session. The credentials are still valid, so do not re-register."}{ "error": "not_found", "message": "The resource does not exist, for example a deleted tweet or a private account."}{ "error": "rate_limited", "message": "Too many requests. Back off and retry with exponential backoff."}{ "error": "server_error", "message": "Something failed on our side. Retry with backoff; if it persists, contact support."}Pricing
| Unit | Price |
|---|---|
| Per call | $0.0008 |
| Per 1,000 calls | $0.80 |
When to use
Use it to verify a follow edge between two accounts, for example confirming whether a lead follows your brand before outreach.
Related endpoints
- User Followers: Page through the accounts that follow a user.
- User Following: Page through the accounts a user follows.
- User Info by ID: Fetch a full profile by numeric user ID.
FAQ
What flags does the relationship object include?
It returns following, followed_by, blocking, blocked_by, muting, and can_dm, plus the source and target IDs, in one directional object.
What identifiers does it take?
For each side, a numeric user ID (source_user_id, target_user_id) or a username (source_username, target_username). A username is resolved to its ID first, and an unknown username returns a 404 that is not billed. When both are sent for one side, the ID wins.
What happens if a user is not found?
An unknown username or user ID returns a 404 with error not_found and is not billed. relationship can still be null when X answers without a relationship object, so check for null before reading flags.
User Affiliates GET
Return the affiliated accounts linked under an organization's Verified Organizations profile. Useful for mapping a company to its employees and brand accounts. Cost: $0.0008 per call.
Blocked Accounts GET
Return the accounts blocked by the account behind your registered session, as full user objects, cursor-paginated. This reads your OWN block list. There is no user_id parameter because X exposes no way to read another account's blocks, so the endpoint does not pretend to offer one. Requires a registered session or per-call inline credentials. Cost: $0.0008 per call.