> ## Documentation Index
> Fetch the complete documentation index at: https://docs.xquik.com/llms.txt
> Use this file to discover all available pages before exploring further.

# How to see who liked my tweet with Twitter API

> See who liked a tweet with user profiles, follower counts, verification fields, cursor checkpoints, visibility limits & exact Twitter API examples for exports.

<Panel>
  <Tabs defaultTabIndex={0} sync={false}>
    <Tab title="200" id="response-x-favoriters-200">
      ```json theme={null}
      {
        "users": [],
        "has_next_page": false,
        "next_cursor": ""
      }
      ```
    </Tab>

    <Tab title="400" id="response-x-favoriters-400">
      ```json theme={null}
      {
        "error": "invalid_input",
        "message": "Invalid input. Check the request body."
      }
      ```
    </Tab>

    <Tab title="401" id="response-x-favoriters-401">
      ```json theme={null}
      {
        "error": "unauthenticated",
        "message": "Authentication required. Provide a valid API key or bearer token."
      }
      ```
    </Tab>

    <Tab title="402" id="response-x-favoriters-402">
      ```json theme={null}
      {
        "error": "insufficient_credits",
        "message": "Insufficient credits. Top up or subscribe to continue."
      }
      ```
    </Tab>

    <Tab title="403" id="response-x-favoriters-403">
      ```json theme={null}
      {
        "error": "forbidden",
        "message": "This API key can access paid read endpoints only."
      }
      ```
    </Tab>

    <Tab title="424" id="response-x-favoriters-424">
      ```json theme={null}
      {
        "error": "favoriters_unavailable",
        "message": "Users who liked this post are unavailable. Use retweeters or replies instead."
      }
      ```
    </Tab>

    <Tab title="429" id="response-x-favoriters-429">
      ```json theme={null}
      {
        "error": "rate_limit_exceeded",
        "message": "Too many requests. Try again later.",
        "retryAfter": 60
      }
      ```
    </Tab>

    <Tab title="502" id="response-x-favoriters-502">
      ```json theme={null}
      {
        "error": "x_api_unavailable",
        "message": "X data source temporarily unavailable. Try again later."
      }
      ```
    </Tab>

    <Tab title="503" id="response-x-favoriters-503">
      ```json theme={null}
      {
        "error": "x_api_unavailable",
        "message": "Xquik is busy right now. Retry shortly."
      }
      ```
    </Tab>
  </Tabs>
</Panel>

<blockquote className="agent-llms-directive">
  For the complete documentation index, see <a href="/llms.txt">llms.txt</a>.
</blockquote>

Requested result counts are upper bounds for paid authenticated calls. When remaining credits cannot cover the full page or ID list, Xquik returns fewer results. If zero paid results are affordable, it returns `402 insufficient_credits`.

<Callout icon="coins" color="#5c3327">
  **1 credit per result returned** · [All plans](https://xquik.com/#pricing) from \$0.00012/credit
</Callout>

This route shows who liked one tweet. It returns the likers your connected X
account can see. X shows likers only to the post author. Use
[Connect X account](/api-reference/x-accounts/connect) to add the author's
account. Callers without a connected X account get `424 account_required`.
Guest keys get `403 forbidden`. When your connected X accounts are busy, the
route returns `503`. The route is `GET /api/v1/x/tweets/{id}/favoriters`.

<Warning>
  X does not expose liker identities for every post. When a post reports likes
  but no liker identities are available, the endpoint returns `424
      favoriters_unavailable`. Do not interpret this error as zero likes or proof
  that a specific user did not participate.
</Warning>

<CodeGroup>
  ```bash First page theme={null}
  curl https://xquik.com/api/v1/x/tweets/1893456789012345678/favoriters \
    -H "x-api-key: xq_your_api_key_here" | jq
  ```

  ```bash Next page theme={null}
  curl -G https://xquik.com/api/v1/x/tweets/1893456789012345678/favoriters \
    --data-urlencode "cursor=abc123" \
    -H "x-api-key: xq_your_api_key_here" | jq
  ```

  ```javascript Node.js theme={null}
  const tweetId = "1893456789012345678";
  const response = await fetch(`https://xquik.com/api/v1/x/tweets/${tweetId}/favoriters`, {
    headers: { "x-api-key": "xq_your_api_key_here" },
  });
  const data = await response.json();
  if (!response.ok) throw new Error(JSON.stringify(data));
  const nextCursor = data.has_next_page ? data.next_cursor : null;
  const likerRows = data.users.map((user) => ({
    source_tweet_id: tweetId,
    liker_id: user.id,
    username: user.username,
    display_name: user.name,
    follower_count: user.followers ?? null,
    following_count: user.following ?? null,
    verified: user.verified ?? false,
    verified_type: user.verifiedType ?? null,
    profile_image_url: user.profilePicture ?? null,
  }));
  const checkpoint = { source_tweet_id: tweetId, next_cursor: nextCursor };

  for (const row of likerRows) {
    process.stdout.write(`${JSON.stringify(row)}\n`);
  }
  process.stdout.write(`${JSON.stringify({ checkpoint })}\n`);
  ```

  ```python Python theme={null}
  import json
  import requests

  tweet_id = "1893456789012345678"
  response = requests.get(
      f"https://xquik.com/api/v1/x/tweets/{tweet_id}/favoriters",
      headers={"x-api-key": "xq_your_api_key_here"},
  )
  data = response.json()
  response.raise_for_status()
  next_cursor = data["next_cursor"] if data["has_next_page"] else None
  liker_rows = [
      {
          "source_tweet_id": tweet_id,
          "liker_id": user["id"],
          "username": user["username"],
          "display_name": user["name"],
          "follower_count": user.get("followers"),
          "following_count": user.get("following"),
          "verified": user.get("verified", False),
          "verified_type": user.get("verifiedType"),
          "profile_image_url": user.get("profilePicture"),
      }
      for user in data["users"]
  ]
  checkpoint = {"source_tweet_id": tweet_id, "next_cursor": next_cursor}
  for row in liker_rows:
      print(json.dumps(row))
  print(json.dumps({"checkpoint": checkpoint}))
  ```
</CodeGroup>

The Node.js and Python snippets write JSON Lines liker rows plus a separate
checkpoint. They do not write raw response pages. Store each mapped row and the latest
`next_cursor`. An import, giveaway verifier, CRM sync, or agent job can then resume
from the last completed page without duplicate rows.

## Direct tweet liker handoff

Use `GET /api/v1/x/tweets/{id}/favoriters` when a workflow needs one row per
visible account that liked a post. Use these rows for giveaway checks, CRM
imports, audience reviews, or follow-up jobs. Store `source_tweet_id`,
`liker_id`, `username`, `display_name`, `follower_count`, `following_count`,
`verified`, `verified_type`, `profile_image_url`, and `next_cursor`.

<CardGroup cols={2}>
  <Card title="Liker rows" icon="rows-3">
    Store `users[]` as the visible profile rows for accounts that liked the
    source post.
  </Card>

  <Card title="Stable upserts" icon="key-round">
    Store `users[].id` as `liker_id` with `source_tweet_id` for idempotent
    imports and giveaway checks.
  </Card>

  <Card title="Readable labels" icon="badge">
    Store `users[].username` and `users[].name` for handles, labels, and review
    queues.
  </Card>

  <Card title="Profile enrichment" icon="file-text">
    Store `description`, `location`, `url`, and `profilePicture` when returned
    for CRM and warehouse enrichment.
  </Card>

  <Card title="Audience signals" icon="chart-no-axes-combined">
    Store `followers`, `following`, `verified`, and `verifiedType` for scoring,
    filters, and outreach priority.
  </Card>

  <Card title="Approved contact" icon="message-square">
    Use DM endpoints only after a user-approved message flow. The write
    response tells you whether X delivered the DM.
  </Card>

  <Card title="Next page" icon="arrow-right">
    Store `has_next_page` and `next_cursor`, then pass `next_cursor` back as `cursor`
    only when `has_next_page` is true.
  </Card>

  <Card title="Credit-limited pages" icon="coins">
    Use `users.length`, not a requested page size, for row counts. Low balances
    can return fewer rows.
  </Card>
</CardGroup>

Direct tweet liker reads cost 1 credit per user returned. Low credit balances
can return fewer users than a full page. Zero affordable results return
`402 insufficient_credits`.

## Tweet liker questions

### How do I see who liked my tweet?

Connect the X account that posted the tweet. Pass the tweet's numeric ID. The
response lists visible user profiles. Continue pagination only when the response
confirms another page.
[X documents this read intent as Get Liking Users.](https://docs.x.com/x-api/posts/get-liking-users)

### Why can't I see who liked my tweet?

X does not expose every liker set. A tweet can show a like count while its liker
profiles remain hidden. `424 favoriters_unavailable` does not mean zero likes.
Deleted, protected, blocked, or withheld accounts may not appear. Without a
connected X account, the route returns `424 account_required`.

### Does this show an account's private likes?

No. This endpoint returns visible users for one source tweet. It does not return
an account's Likes tab or private like history.

### How do I export tweet likers?

The Node.js and Python examples write one JSON Lines row per visible user. Store
the source tweet ID beside each profile. Use `next_cursor` to resume an export.
Use `toolType=favoriters` for a saved CSV, JSON, or XLSX job.

### How can I track and analyze tweet likes?

Run timestamped snapshots and compare them by numeric user ID. This read
endpoint does not send notifications for future likes. A like does not prove
endorsement, purchase intent, or affiliation. Report only returned fields.

## Path parameters

<ParamField path="id" type="string" required>
  Post ID or URL-encoded post URL, such as `x.com/nasa/status/20`. See [path IDs](/api-reference/overview#path-ids).
</ParamField>

## Query parameters

<ParamField query="cursor" type="string">
  Pagination cursor from `next_cursor` in a previous response. Omit it on the
  initial request. Pass it only when `has_next_page` is true.
</ParamField>

<ParamField query="pageSize" type="integer">
  Profiles per page. Range: `20-200`. Defaults to `200`.
</ParamField>

## Which tweet engagement endpoint?

<CardGroup cols={2}>
  <Card title="Tweet likers" icon="heart">
    Use `GET /x/tweets/{id}/favoriters` for user profiles that liked one source
    tweet.
  </Card>

  <Card title="Retweeters" icon="repeat-2">
    Use [`GET /x/tweets/{id}/retweeters`](/api-reference/x/retweeters) for user
    profiles that reposted one source tweet.
  </Card>

  <Card title="Quote tweets" icon="quote">
    Use [`GET /x/tweets/{id}/quotes`](/api-reference/x/tweet-quotes) when you
    need tweet rows that quote the source tweet.
  </Card>

  <Card title="Tweet replies" icon="message-square-reply">
    Use [`GET /x/tweets/{id}/replies`](/api-reference/x/tweet-replies) when you
    need reply tweet rows under the source tweet.
  </Card>

  <Card title="Saved exports" icon="file-spreadsheet">
    Use [`Create extraction`](/api-reference/extractions/create) with
    `toolType=favoriters` when you need a saved job or CSV, JSON, or XLSX
    export.
  </Card>

  <Card title="DM handoff" icon="send">
    Use [`Send DM`](/api-reference/x-write/send-dm) only after your workflow has
    a user-approved outreach step.
  </Card>
</CardGroup>

### User result filters

These filters apply before billing. Selective filters can return fewer rows.

<ParamField query="minFollowers" type="integer">
  Require this minimum follower count. Filtering happens before billing.
</ParamField>

<ParamField query="maxFollowers" type="integer">
  Allow this maximum follower count. Missing counts pass this filter.
</ParamField>

<ParamField query="minFollowing" type="integer">
  Require this minimum following count.
</ParamField>

<ParamField query="maxFollowing" type="integer">
  Allow this maximum following count. Missing counts pass this filter.
</ParamField>

<ParamField query="minStatuses" type="integer">
  Require this minimum post count.
</ParamField>

<ParamField query="maxStatuses" type="integer">
  Allow this maximum post count. Missing counts pass this filter.
</ParamField>

<ParamField query="minAccountAgeDays" type="integer">
  Require this minimum account age in days.
</ParamField>

<ParamField query="verifiedOnly" type="boolean">
  When `true`, only return verified profiles.
</ParamField>

<ParamField query="verifiedType" type="string">
  Match the exact verification type.
</ParamField>

<ParamField query="hasWebsite" type="boolean">
  When `true`, require a profile website.
</ParamField>

<ParamField query="hasLocation" type="boolean">
  When `true`, require a profile location.
</ParamField>

<ParamField query="bioContains" type="string">
  Require every comma-separated or line-separated bio term.
</ParamField>

<ParamField query="locationContains" type="string">
  Require this text in the profile location.
</ParamField>

<ParamField query="usernameContains" type="string">
  Require this text in the username.
</ParamField>

## Headers

<ParamField header="x-api-key" type="string">
  Full account key. Sessions and OAuth also work.
</ParamField>

## Response

### 200 OK

<ResponseField name="users" type="object[]">
  Array of visible users who liked the post.
  **User object fields.**

  <ResponseField name="id" type="string">
    X user ID.
  </ResponseField>

  <ResponseField name="username" type="string">
    X username.
  </ResponseField>

  <ResponseField name="name" type="string">
    Display name.
  </ResponseField>

  <ResponseField name="description" type="string">
    Profile bio.
  </ResponseField>

  <ResponseField name="followers" type="number">
    This value records the follower count.
  </ResponseField>

  <ResponseField name="following" type="number">
    Following count.
  </ResponseField>

  <ResponseField name="verified" type="boolean">
    Verified status.
  </ResponseField>

  <ResponseField name="profilePicture" type="string">
    Profile image URL.
  </ResponseField>

  <ResponseField name="location" type="string">
    Profile location.
  </ResponseField>

  <ResponseField name="createdAt" type="string">
    Account creation date (ISO 8601).
  </ResponseField>

  <ResponseField name="statusesCount" type="number">
    This value records the total tweet count. X may omit it.
  </ResponseField>

  <ResponseField name="coverPicture" type="string">
    This value contains the cover image URL. X may omit it.
  </ResponseField>

  <ResponseField name="mediaCount" type="number">
    This value records the media tweet count. X may omit it.
  </ResponseField>

  <ResponseField name="url" type="string">
    Website URL from profile. Omitted if empty.
  </ResponseField>

  <ResponseField name="favouritesCount" type="number">
    This value records the liked tweet count. X may omit it.
  </ResponseField>

  <ResponseField name="hasCustomTimelines" type="boolean">
    X sets this flag for accounts with custom timelines. X may omit it.
  </ResponseField>

  <ResponseField name="isTranslator" type="boolean">
    X sets this flag for translator accounts. X may omit it.
  </ResponseField>

  <ResponseField name="withheldInCountries" type="string[]">
    Country codes where the account is withheld. Omitted if empty.
  </ResponseField>

  <ResponseField name="possiblySensitive" type="boolean">
    X sets this flag for sensitive accounts. X may omit it.
  </ResponseField>

  <ResponseField name="pinnedTweetIds" type="string[]">
    This array contains pinned tweet IDs. Omitted if none.
  </ResponseField>

  <ResponseField name="isAutomated" type="boolean">
    X sets this flag for automated accounts. X may omit it.
  </ResponseField>

  <ResponseField name="automatedBy" type="string">
    Username of the account operator if automated. Omitted if not automated.
  </ResponseField>

  <ResponseField name="unavailable" type="boolean">
    X sets this flag when it cannot return the account.
  </ResponseField>

  <ResponseField name="unavailableReason" type="string">
    X may give a reason for a missing account.
  </ResponseField>

  <ResponseField name="verifiedType" type="string">
    Verification type (for example `Business`, `Government`). Omitted if not verified or standard blue
    check.
  </ResponseField>

  <ResponseField name="profile_bio" type="object">
    Use this object for bio text and linked profile entities. X may omit it.
  </ResponseField>

  <ResponseField name="isBlueVerified" type="boolean">
    X sets this flag for X Premium verification. X may omit it.
  </ResponseField>

  <ResponseField name="isVerified" type="boolean">
    Use this field for normalized verification status. X may omit it.
  </ResponseField>

  <ResponseField name="profileBannerUrl" type="string">
    This value contains the profile banner URL. X may omit it.
  </ResponseField>

  <ResponseField name="protected" type="boolean">
    X sets this flag for protected accounts. X may omit it.
  </ResponseField>

  <ResponseField name="communityRole" type="string">
    Role within the requested community context. Omitted outside community results.
  </ResponseField>
</ResponseField>

<ResponseField name="has_next_page" type="boolean">
  Whether more results are available.
</ResponseField>

<ResponseField name="next_cursor" type="string">
  Opaque cursor for the next page. Empty string when no more results.
</ResponseField>

### 401 Unauthenticated

```json theme={null}
{ "error": "unauthenticated" }
```

Missing or invalid API key.

### 402 Payment required

Account users can subscribe or add credits.
Confirm payment before continuing.

<Note>
  **Related.** [Retweeters](/api-reference/x/retweeters) · [Quote tweets](/api-reference/x/tweet-quotes) · [Tweet replies](/api-reference/x/tweet-replies)
</Note>

<div className="related-api-links">
  <Accordion title="Related tweet, reply & media APIs" icon="link">
    * Tweets: [Get tweet](/api-reference/x/get-tweet) · [Batch tweets](/api-reference/x/batch-tweets) · [Tweet thread](/api-reference/x/tweet-thread) · [Hidden replies](/api-reference/x/tweet-hidden-replies) · [Translate tweet](/api-reference/x/tweet-translation) · [Embed tweet](/api-reference/x/tweet-embed) · [Resolve links](/api-reference/x/resolve-links) · [Tweet subtitles](/api-reference/x/tweet-subtitles) · [X Article](/api-reference/x/get-article)
    * Analysis: [Sentiment analysis](/api-reference/x/sentiment-analysis) · [Brand mentions](/api-reference/x/brand-monitoring) · [News classification](/api-reference/x/news-classification) · [Market signals](/api-reference/x/market-signals) · [Viral score](/api-reference/x/viral-score) · [Classify posts](/api-reference/x/classify-tweets)
    * Engagement: [Tweet replies](/api-reference/x/tweet-replies) · [Quote tweets](/api-reference/x/tweet-quotes) · [Likers](/api-reference/x/favoriters) · [Reposters](/api-reference/x/retweeters) · [Check repost](/api-reference/x/tweet-repost-check)
    * Profiles: [User tweets](/api-reference/x/user-tweets) · [Batch user tweets](/api-reference/x/batch-user-tweets) · [User replies](/api-reference/x/user-replies) · [User likes](/api-reference/x/user-likes) · [User media](/api-reference/x/user-media) · [User highlights](/api-reference/x/user-highlights) · [User articles](/api-reference/x/user-articles)
    * Feeds: [List tweets](/api-reference/x/list-tweets) · [Trends](/api-reference/x/trends) · [Trend locations](/api-reference/x/trend-locations) · [Search Spaces](/api-reference/x/search-spaces) · [Get Space](/api-reference/x/get-space) · [Space replay](/api-reference/x/space-replay) · [Get broadcast](/api-reference/x/get-broadcast) · [Hashflags](/api-reference/x/hashflags) · [Search places](/api-reference/x/search-places) · [Download media](/api-reference/x/download-media)
  </Accordion>
</div>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.