Skip to content

Verify Twitter follows and retweets by API

An API verifies an X follow, retweet, quote or reply by checking one account against one action and answering true or false; the official X API has no such check, so there it means reading whole lists at $0.010 per account.

Short answer: Each action gets its own check: follow, retweet, quote, reply or Community join. Likes get none, because since June 2024 only a post's author sees who liked it. Sorsa API answers each check in one request, POST /check-follow and four more, from $1.40 per 1,000 checks; your 100 free requests cover the first 100.

/check-follow + 4 more
1 request per check
Price
from $0.0014 per check

#What you can verify on X, and what you can't

Five actions on X are public, so an API can confirm each of them for one account at a time: a follow, a retweet, a quote, a reply and a Community membership. Verification here means proof that one account did one thing, such as following you or reposting your post; it has nothing to do with X's blue checkmark.

For a single pair of accounts, the free Twitter Follow Checker shows whether one follows the other, both ways, with no code. To draw winners from a post's reposts, replies and quotes, the free X (Twitter) Giveaway Picker checks each drawn winner's follow. Checking every entrant of a campaign takes an API.

Every task except a like can be proved, but the official X API proves none of them directly: it hands you lists to search, and has no route at all for Community membership.

TaskWhat a check needsOfficial X API route
Followed an accountboth handlesread a following or follower list
Retweeted a postthe post link and the handleread the post's retweeters, 100 a page
Quoted a postthe post link and the handleread the post's quotes
Replied to a postthe post link and the handlesearch the post's conversation
Joined an X Communitythe Community and the handleno endpoint
Owns the handlethe handle and a code they postread the account's posts
Liked a postcan't be checkedonly the post's author sees likers
  • Followed an account

    What a check needs
    both handles
    Official X API route
    read a following or follower list
  • Retweeted a post

    What a check needs
    the post link and the handle
    Official X API route
    read the post's retweeters, 100 a page
  • Quoted a post

    What a check needs
    the post link and the handle
    Official X API route
    read the post's quotes
  • Replied to a post

    What a check needs
    the post link and the handle
    Official X API route
    search the post's conversation
  • Joined an X Community

    What a check needs
    the Community and the handle
    Official X API route
    no endpoint
  • Owns the handle

    What a check needs
    the handle and a code they post
    Official X API route
    read the account's posts
  • Liked a post

    What a check needs
    can't be checked
    Official X API route
    only the post's author sees likers

X made likes private on June 11, 2024: a post's author still sees who liked it, but nobody else does (Engadget, quoting X Engineering (opens in a new tab)). Swap "like this post" for a retweet, a quote or a reply; all three stay public and checkable.

#Six checks on Sorsa API, one request each

To verify campaign tasks entrant by entrant, use Sorsa API, a Twitter (X) API and scraper: each check is one request that answers true or false, from $0.0014 per check, with one API key, no OAuth and 20 requests per second on every plan.

Five endpoints cover the five public actions, and a sixth request reads an entrant's latest posts for an ownership code.

TaskSorsa API requestWhat comes back
Followed your accountPOST /check-followfollow: true or false
Retweeted your postPOST /check-retweetretweet, and next_cursor past the newest 100
Quoted your postPOST /check-quotedstatus: quoted, retweet or not_found, with the quote's text
Replied to your postGET /check-commentcommented, and the reply itself
Joined your X CommunityPOST /check-community-memberis_member: true or false
Owns the handlePOST /user-tweetstheir latest posts, where you look for the code
  • Followed your account

    Sorsa API request
    POST /check-follow
    What comes back
    follow: true or false
  • Retweeted your post

    Sorsa API request
    POST /check-retweet
    What comes back
    retweet, and next_cursor past the newest 100
  • Quoted your post

    Sorsa API request
    POST /check-quoted
    What comes back
    status: quoted, retweet or not_found, with the quote's text
  • Replied to your post

    Sorsa API request
    GET /check-comment
    What comes back
    commented, and the reply itself
  • Joined your X Community

    Sorsa API request
    POST /check-community-member
    What comes back
    is_member: true or false
  • Owns the handle

    Sorsa API request
    POST /user-tweets
    What comes back
    their latest posts, where you look for the code

Every check takes the entrant as a handle, a numeric user ID or a profile link, and the post as a link or a bare ID. The answers carry more than a yes: the quote's text, the reply itself, and a user_protected flag on the follow, retweet and quote checks when an entrant's account is private. Your own X account never takes part, so no campaign puts it at risk.

#Check one entrant in four steps

Checking one entrant takes one request per task. This example checks a follow, a retweet and a reply, the most common giveaway rules, with the key in the ApiKey header.

  1. Get a key. Sign up and copy your API key from the dashboard. The first 100 requests are free and need no card.

  2. Check the follow. Send your handle as username_1 and the entrant's as username_2.

    Terminal
    curl -X POST "https://api.sorsa.io/v3/check-follow" \
      -H "ApiKey: YOUR_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{"username_1": "lumenharbor_labs",
           "username_2": "maya_quest_runner"}'
    
    Response200 OK
    {
      "follow": true,
      "user_protected": false
    }
    
  3. Check the post tasks. Send your post's link and the entrant's handle to POST /check-retweet in a JSON body and to GET /check-comment as query parameters.

  4. Combine the answers. Mark the entrant eligible only when every required check came back true, and keep each answer for the record.

    import requests
    
    BASE = "https://api.sorsa.io/v3"
    HEADERS = {"ApiKey": "YOUR_API_KEY"}
    BRAND = "lumenharbor_labs"
    POST = "https://x.com/lumenharbor_labs/status/2115459618305512658"
    
    
    def call(method, path, **kwargs):
        r = requests.request(method, BASE + path, headers=HEADERS,
                             timeout=20, **kwargs)
        r.raise_for_status()
        return r.json()
    
    
    def verify_entrant(handle):
        follow = call("POST", "/check-follow",
                      json={"username_1": BRAND, "username_2": handle})
        retweet = call("POST", "/check-retweet",
                       json={"tweet_link": POST, "username": handle})
        reply = call("GET", "/check-comment",
                     params={"tweet_link": POST, "username": handle})
        result = {
            "handle": handle,
            "follow": follow["follow"],
            "retweet": retweet["retweet"],
            "reply": reply["commented"],
            "protected": follow.get("user_protected", False),
        }
        result["eligible"] = all(
            result[k] for k in ("follow", "retweet", "reply"))
        return result
    
    
    print(verify_entrant("maya_quest_runner"))
    

Three checks, three requests: this entrant cost from $0.0042 to verify. A 403 means the key is missing or its requests have run out. A 429 means more than 20 requests landed in one second: wait a second and send it again. Failed requests are never charged.

#Check if one X account follows another

POST /check-follow (opens in a new tab) answers whether the second account follows the first: username_1 is the account that should be followed, username_2 is the account you check, and follow comes back true or false in one request, however many followers either side has.

Each side takes one identifier: a handle, a numeric ID (user_id_1, user_id_2) or a profile link (user_link_1, user_link_2). The answer covers one direction, so a mutual follow takes two calls with the sides swapped. When user_protected is true, the checked account is protected: its follows aren't public, and no outside service can confirm them.

The official X API has no endpoint that answers one pair. Its route reads a whole list instead: GET /2/users/:id/following returns up to 1,000 accounts a page, billed at $0.010 per account under Following/Followers: Read on X's pay-per-use rate card (opens in a new tab). An entrant who follows 800 accounts costs up to $8 to check that way, and reading your own list of 50K followers costs $500 a pull.

Official X API Read a whole list GET /2/users/:id/following Page until it turns up 1,000 accounts a page Found or not $0.010 / account Needs an approved developer account, an app and its tokens first. Sorsa API One request POST /check-follow {"follow": true} from $0.0014 per check, one API key, no OAuth
The official X API answers "does A follow B?" only by reading a list; Sorsa API answers it in one request.

#Check if a user retweeted your post

POST /check-retweet (opens in a new tab) scans your post's retweets 100 at a time, newest first, and returns retweet: true once it finds the entrant; when the first 100 don't hold them, next_cursor continues with the next 100.

A retweet checked while the entrant waits, for example right after they press "Verify" on a quest page, sits among the newest 100, so one request answers it. An entrant who reposted at launch on a viral post sits deeper: the loop below follows the cursor up to a cap you choose and reports "not checked yet" instead of "no" when the cap runs out.

Your post's retweets, newest first older Request 1 retweets 1 to 100 Request 2 retweets 101 to 200 Request 3 retweets 201 to 300 … next_cursor next_cursor Reposted a minute ago found in request 1 Reposted at launch found in request 3 Stop at retweet: true. An empty next_cursor with retweet: false means no retweet.
A retweet made minutes ago turns up in the first request; one from launch day on a big post takes one more request per 100 retweets.
Python
def retweeted(post, handle, max_pages=10):  # 10 pages = 1,000 retweets
    body = {"tweet_link": post, "username": handle}
    for _ in range(max_pages):
        page = call("POST", "/check-retweet", json=body)
        if page["retweet"]:
            return "yes"
        if not page.get("next_cursor"):
            return "no"
        body["next_cursor"] = page["next_cursor"]
    return "not checked yet"

The official X API reads the same list through GET /2/tweets/:id/retweeted_by: 100 accounts a page at $0.010 each, and 75 requests per 15 minutes per app, which caps a pull at 7,500 retweeters per window (X API rate limits (opens in a new tab)).

#Verify quotes, replies and Community joins

Three more checks cover the rest of a campaign: POST /check-quoted (opens in a new tab) tells a quote from a plain retweet, GET /check-comment (opens in a new tab) returns the entrant's reply itself, and POST /check-community-member (opens in a new tab) answers whether they joined your X Community.

/check-quoted returns status as quoted, retweet (they reposted without a comment) or not_found, and adds the quote's text and date when there is one. That text is what lets you enforce rules such as a minimum length or a campaign hashtag.

Response200 OK
{
  "status": "quoted",
  "date": "2026-10-28 15:21:47",
  "text": "Joined the Lumen Harbor beta. The queue tool is quick #LumenBeta",
  "user_protected": false
}

/check-comment takes the post's tweet_link and the entrant as query parameters and, when commented is true, returns the full reply: its full_text, created_at and engagement counts, so emoji-only or copied replies can fail your rules. To read all the replies under a post at once, see how to see comments on X.

/check-community-member takes community_id or community_link, each accepting the numeric ID or the full x.com/i/communities/ URL, plus the entrant, and returns is_member. The official X API can look a Community up by ID or search for one, but has no endpoint that lists members or checks membership.

#Verify a giveaway from entries to payout

A verified giveaway runs in three steps: collect each entrant's handle, run one check per required task, and pay only the entrants who passed every check.

  1. Collect handles and a code. Ask for the X handle in your entry form and show each entrant a short one-time code to post, so you can prove the handle is theirs (next section).

  2. Run one check per task. Check at entry for an instant answer, or after entries close; the chart below picks the cheaper route for your size.

  3. Re-check, then pay. Run /check-follow again on the winners before payout, because some entrants unfollow once they've entered, then draw only from entrants who passed everything.

    When do you check? While the entrant waits a quest button, a sign-up form One check per task /check-follow, /check-retweet … one request each; a fresh retweet sits among the newest 100 After entries close a giveaway draw, an airdrop list Hundreds of entrants: one check per task for each entrant Thousands pull each list once, match account IDs Before payout, re-check each winner's follow with one more /check-follow
    Check at entry for instant answers; for a closed campaign of thousands, pull each list once and match IDs.

The list route pays off once entrants run into the thousands: GET /followers (opens in a new tab) returns 200 followers a page and POST /retweeters (opens in a new tab) 20 retweeters a page, newest first, so 10K retweeters take 500 requests instead of 10K checks. The guide to export Twitter followers has the cursor loop for the follower list; match both lists on account id, which never changes when a handle does.

X's own Guidelines for Promotions on X (opens in a new tab) ask hosts to rule out entries from multiple accounts and repeated identical posts, and warn that a public search may not show every entry. Checking each entrant by handle avoids that gap, because the check never depends on search; the ownership code and profile filter below keep borrowed and throwaway accounts out.

#Stop fake handles and bots before you pay

Two cheap checks keep borrowed handles and bot farms out of a payout: an ownership code read with POST /user-tweets (opens in a new tab), and a profile filter through GET /info-batch (opens in a new tab), 100 entrants per request.

The ownership code works because only the account's owner can post from it: give each entrant a code such as LUMEN-7Q4K, then read their latest posts, up to 20 per request, and look for it.

Python
from datetime import datetime, timedelta, timezone

CUTOFF = datetime.now(timezone.utc) - timedelta(days=30)


def owns_handle(handle, code):
    page = call("POST", "/user-tweets", json={"username": handle})
    return any(code in t["full_text"] for t in page.get("tweets", []))


def looks_real(user):
    joined = datetime.fromisoformat(
        user["created_at"].replace("Z", "+00:00"))
    return (joined < CUTOFF and user["tweets_count"] >= 10
            and user["followers_count"] >= 5)


def real_entrants(handles):
    keep = []
    for i in range(0, len(handles), 100):
        batch = {"usernames": handles[i:i + 100]}
        users = call("GET", "/info-batch", params=batch)["users"]
        keep += [u["username"] for u in users if looks_real(u)]
    return keep

The filter above drops accounts younger than 30 days, with fewer than 10 posts or fewer than 5 followers; tune the numbers to your audience. Profiles cost from $0.014 per 1,000, so filtering 10K entrants costs from $0.14. For scoring a suspicious list in more depth, the guide to Twitter bot detection covers the signals that separate bots from people.

Good to know

Keep "didn't do it" apart from "couldn't check". A 429, a timeout or a retweet loop that hit its cap means the entrant isn't checked yet, not that they failed. Store that state, retry later, and reject an entrant only on a clear false.

#What a campaign costs to verify

Verifying a campaign on Sorsa API costs one request per task per entrant, from $0.0014 each; on the official X API the same proof means reading whole lists, at $0.010 per account and $0.005 per post.

Task by task, the Sorsa API column stays at one request, while the official X API column grows with every list it reads, and has no entry at all for Community membership.

TaskSorsa APIOfficial X API route and price
Follow1 request, from $0.0014Read a follower or following list, $0.010 per account
Retweet1 request at entry, from $0.0014Read retweeted_by, $0.010 per account, 75 requests per 15 min
Quote1 request, from $0.0014Read quote posts, $0.005 per post
Reply1 request, from $0.0014Search the conversation, $0.005 per post
Community1 request, from $0.0014No endpoint
Ownership code1 request, from $0.0014Read the user's posts, 5 at least: $0.025
  • Follow

    Sorsa API
    1 request, from $0.0014
    Official X API route and price
    Read a follower or following list, $0.010 per account
  • Retweet

    Sorsa API
    1 request at entry, from $0.0014
    Official X API route and price
    Read retweeted_by, $0.010 per account, 75 requests per 15 min
  • Quote

    Sorsa API
    1 request, from $0.0014
    Official X API route and price
    Read quote posts, $0.005 per post
  • Reply

    Sorsa API
    1 request, from $0.0014
    Official X API route and price
    Search the conversation, $0.005 per post
  • Community

    Sorsa API
    1 request, from $0.0014
    Official X API route and price
    No endpoint
  • Ownership code

    Sorsa API
    1 request, from $0.0014
    Official X API route and price
    Read the user's posts, 5 at least: $0.025

A worked example: 10K entrants, your account has 50K followers, and the campaign asks for a follow, a retweet, a quote, a reply and a Community join, plus an ownership code, a profile filter and a follow re-check before payout. That is 7 checks per entrant, and the whole campaign costs from $98 on Sorsa API, about an hour of work at 20 requests per second. The official X API route for the same campaign, without the Community check it can't run, comes to about $1,550: two pulls of your follower list at $500 each, $100 of retweeters, $100 of quotes and replies, $250 of timelines for the ownership codes and $100 of profiles.

10K
50K
Tasks you check
$1,550
Official X API
Your follower list, retweeters and profiles at $0.010 each, posts at $0.005. No Community check, so it's left out.
from $98
Sorsa API
$1.40 per 1,000 requests; $139 at the Pro rate of $1.99.

7 checks per entrant, about 58 minutes for everyone at 20 requests per second.

Set your entrants, your follower count and the tasks; both totals change with them.

Sorsa API bills requests, not accounts, and failed requests are never charged. The rate per 1,000 requests runs from $4.90 on Starter to $1.40 on the largest plan.

#Run your first 100 checks free

To verify follows, retweets, quotes, replies and Community joins for every entrant, use Sorsa API: one request per check, from $0.0014, 20 requests per second on every plan, and no X login of yours anywhere in the flow. Take the 100 free requests, run the four steps above against a test post, and add the ownership code before your campaign opens. For whole follower and following lists, the list route in the Twitter followers API guide goes further.

#FAQ

What is the best API to verify Twitter follows and retweets?

Sorsa API: it checks follows, retweets, quotes, replies and Community membership with one request each, from $0.0014 per check, through one API key with no OAuth or X developer account. Judge any option on four points: a direct yes or no per entrant, the price per check, the rate limit and the actions covered. Sorsa API meets all four: one call, $1.40 per 1,000 checks, 20 requests per second on every plan, six checks.

Can I verify likes on X?

No. Since June 2024 X shows who liked a post only to the post's author, so a public data API can't confirm that one entrant liked it, and Sorsa API returns no likes. Ask entrants to retweet, quote or reply instead: all three stay public, and Sorsa API checks each with one request.

What happens if an entrant's account is private?

A protected account's follows and reposts aren't public, so no outside check can confirm them. Sorsa API's follow, retweet and quote checks return user_protected: true in that case. State in your rules that entrants need a public account during the draw, then ask the entrant to switch or reject the entry under those rules.

Is there a free way to verify Twitter follows and retweets?

Yes. The free Twitter Follow Checker shows whether one account follows another, and the free Giveaway Picker checks each drawn winner's follow. To check every entrant through the API, Sorsa API's 100 free requests run 100 checks with no card, and they never expire, enough to test a whole campaign flow before you pick a plan.

Do I need an X developer account or OAuth to verify tasks?

Not with Sorsa API: one key in the ApiKey header reads public X data, with no X developer account, app, OAuth flow or sign-in from your entrants. The official X API asks for an approved developer account, a Project and App, and their keys and tokens before the first read (X API: Retweets (opens in a new tab)).

#How we checked

On November 2, 2026 we compared every endpoint, parameter and response field in this guide with the live Sorsa API reference (45 endpoints) and its docs pages for the five checks, /user-tweets, /info-batch and /retweeters; the requests and responses use demo accounts. The official X API's prices, rate limits and endpoints come from docs.x.com, and X's promotion rules from its Help Center, read the same day. The campaign costs are our own arithmetic from both rate cards.

By the Sorsa API team. We build and run Sorsa API, the read-only Twitter/X API and scraper, in production since 2022 (formerly TweetScout API) with 6B+ requests served. About Sorsa API

What changed
  • Rewritten from scratch: six checks with requests and responses, the giveaway flow from entries to payout, ownership codes and profile filters, the cost of a campaign against the official X API's rate card read today, and the giveaway verification page merged in.
  • First published.