Docs

API reference

Profiles, posts, and search for X. Authenticate with an API key. Plan limits are per account. Base: https://api.probeuranus.fun

Authentication

Sign in with Google on the dashboard. First login creates your API key (shown once). Use Rotate when you need a new secret; the old one stops working immediately. Send the key with every request.

  • API key: Authorization: Bearer <api_key> (or X-API-Key)

Setup

const BASE = "https://api.probeuranus.fun";
const API_KEY = "probe_...";

Plans & limits

Quota lives on your account and your key inherits it. An account with no active subscription gets 402 subscription_required on every call — the key stays valid and starts working again the moment you subscribe. Check GET /v1/me for remaining quota and reset times, or read these response headers:

  • X-RateLimit-Limit / X-RateLimit-Remaining / X-RateLimit-Reset · per minute
  • X-RateLimit-Limit-Daily / X-RateLimit-Remaining-Daily / X-RateLimit-Reset-Daily · daily (when set)
  • X-RateLimit-Limit-Monthly / X-RateLimit-Remaining-Monthly / X-RateLimit-Reset-Monthly · monthly (when set)
  • X-Plan · your plan name
  • Retry-After · wait time when limited

List responses use { data, next_cursor, cursor, meta }. Pass next_cursor back as ?cursor=. Timelines accept since_id, until_id, include_replies, include_retweets, and media_only.

Plan defaults are on /pricing.

Errors

JSON body shape:

Error shape

{ "error": "code", "message": "optional detail" }
  • 401: missing_api_key, invalid_key, inactive, unauthorized
  • 402: subscription_required — the key is valid but the account has no active subscription. Nothing to rotate; it works again once you subscribe.
  • 429: rate_limited, daily_quota, monthly_quota — body includes message, retryAfterSec, and limitType. Honor Retry-After (seconds). Example:

429 example

{
  "error": "rate_limited",
  "message": "RPM limit reached. Wait 12s, then retry. Check X-RateLimit-* headers and GET /v1/me.",
  "retryAfterSec": 12,
  "limitType": "rpm"
}
  • 404: not_found
  • 503: x_sessions_exhausted, auth_fail (temporary capacity)
  • 502: temporary request failure

Public

No API key required.

GET/healthPublic

Health check

Service liveness plus scraper session pool status (operational | degraded | down).

Node.js

const res = await fetch(`${BASE}/health`);
const data = await res.json();
console.log(data);
GET/v1Public

List available API commands

Full list of available commands.

  • Also available at GET / and GET /v1/commands
  • Also available for API tools at GET /v1/openapi.json

Node.js

const res = await fetch(`${BASE}/v1`);
const data = await res.json();
console.log(data);
GET/v1/openapi.jsonPublic

Schema for API tools

Command list in a format API tools understand.

Node.js

const res = await fetch(`${BASE}/v1/openapi.json`);
const data = await res.json();
console.log(data);

API

Needs your API key. Profile lookups may be briefly cached. Add fresh=1 if you need the newest data.

GET/v1/meAPI key

Current account plan and usage

Returns plan limits, remaining RPM/daily/monthly quota, and reset timestamps for the account that owns this API key.

  • Counts as one request against your account quota
  • Also mirrored on every keyed response via X-RateLimit-* and X-RateLimit-Reset* headers
  • Response envelope: { data, meta }

Node.js

const res = await fetch(`${BASE}/v1/me`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/user/infoAPI key

Get user profile and stats

Returns profile fields, follower/following counts, statuses, media counts, etc. Lookup by handle or numeric rest id.

Parameters

  • userName · query · string

    X handle without @ (alias: username). Provide userName or userId.

  • userId · query · string

    Numeric rest id (alias: user_id). Use when you store ids instead of handles.

  • fresh · query · boolean

    Bypass cache when 1/true/yes

  • include_space · query · boolean

    Look up whether the account is in a live Space (default true). Set 0/false/no to skip.

  • include_broadcast · query · boolean

    Look up whether the account is running a live video broadcast (default true). Set 0/false/no to skip.

  • Response envelope: { data, meta } with meta.cached / meta.fetched_at
  • Cache-Control: private, max-age=60 (or CACHE_TTL_MS capped); weak ETag from user id + fetched_at; 304 on If-None-Match
  • userName takes precedence if both are sent
  • data.currentSpace is live (fleets), not from the profile cache. Pass include_space=0 to skip.
  • data.currentBroadcast is the live video stream they are hosting, or null. X does not expose watchers. Pass include_broadcast=0 to skip.

Node.js

const res = await fetch(`${BASE}/v1/user/info?userName=elonmusk&userId=44196397&fresh=1&include_space=1&include_broadcast=1`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/user/tweetsAPI key

Get latest tweets for a user

User timeline with cursor pagination. Tweets include media[] (url, previewUrl, width/height, durationMs, altText, variants[] with contentType/url/bitrate).

Parameters

  • userName · query · required · string

    X handle without @

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • include_replies · query · boolean

    Include reply tweets (default false on /user/tweets, true elsewhere)

  • include_retweets · query · boolean

    Include retweets (default true)

  • media_only · query · boolean

    Only tweets that have media[] (default false)

  • since_id · query · string

    Keep tweets with id strictly greater than this snowflake (page filter; keep paging with cursor)

  • until_id · query · string

    Keep tweets with id strictly less than this snowflake (exclusive)

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/user/tweets?userName=elonmusk&limit=20&include_replies=0&include_retweets=1&media_only=1`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/user/tweets-and-repliesAPI key

Get tweets and replies for a user

Timeline including the user's replies (UserTweetsAndReplies). Cursor-paginated.

Parameters

  • userName · query · required · string

    X handle without @

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • include_replies · query · boolean

    Include reply tweets (default false on /user/tweets, true elsewhere)

  • include_retweets · query · boolean

    Include retweets (default true)

  • media_only · query · boolean

    Only tweets that have media[] (default false)

  • since_id · query · string

    Keep tweets with id strictly greater than this snowflake (page filter; keep paging with cursor)

  • until_id · query · string

    Keep tweets with id strictly less than this snowflake (exclusive)

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/user/tweets-and-replies?userName=elonmusk&limit=20&include_replies=0&include_retweets=1&media_only=1`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/user/mentionsAPI key

Get tweets mentioning a user

Tweets that mention an account (SearchTimeline `@handle -from:handle`). Cursor-paginated. Not the authenticated user's notification inbox.

Parameters

  • userName · query · required · string

    X handle without @ (alias: username)

  • product · query · string

    Latest or Top (default Latest)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • include_replies · query · boolean

    Include reply tweets (default false on /user/tweets, true elsewhere)

  • include_retweets · query · boolean

    Include retweets (default true)

  • media_only · query · boolean

    Only tweets that have media[] (default false)

  • since_id · query · string

    Keep tweets with id strictly greater than this snowflake (page filter; keep paging with cursor)

  • until_id · query · string

    Keep tweets with id strictly less than this snowflake (exclusive)

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.
  • meta.query is the search string used; equivalent to GET /v1/search/tweets?query=@handle%20-from:handle

Node.js

const res = await fetch(`${BASE}/v1/user/mentions?userName=elonmusk&product=Latest&limit=20&include_replies=0&include_retweets=1&media_only=1`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/search/tweetsAPI key

Search tweets

Latest/Top search over X posts.

Parameters

  • query · query · required · string

    Search query (alias: q). Supports X operators.

  • product · query · string

    Latest or Top (default Latest)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • include_replies · query · boolean

    Include reply tweets (default false on /user/tweets, true elsewhere)

  • include_retweets · query · boolean

    Include retweets (default true)

  • media_only · query · boolean

    Only tweets that have media[] (default false)

  • since_id · query · string

    Keep tweets with id strictly greater than this snowflake (page filter; keep paging with cursor)

  • until_id · query · string

    Keep tweets with id strictly less than this snowflake (exclusive)

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/search/tweets?query=solana&product=Latest&limit=5&include_replies=0&include_retweets=1&media_only=1`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/search/usersAPI key

Search users

People search over X accounts via SearchTimeline (product=People). Cursor-paginated.

Parameters

  • query · query · required · string

    Search query (alias: q)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/search/users?query=solana&limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/user/mediaAPI key

Get media tweets for a user

Media tab timeline (photos/videos/gifs). Cursor-paginated; tweets include media[] (altText and video variants[]).

Parameters

  • userName · query · required · string

    X handle without @ (alias: username)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • include_replies · query · boolean

    Include reply tweets (default false on /user/tweets, true elsewhere)

  • include_retweets · query · boolean

    Include retweets (default true)

  • media_only · query · boolean

    Only tweets that have media[] (default false)

  • since_id · query · string

    Keep tweets with id strictly greater than this snowflake (page filter; keep paging with cursor)

  • until_id · query · string

    Keep tweets with id strictly less than this snowflake (exclusive)

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/user/media?userName=nasa&limit=20&include_replies=0&include_retweets=1&media_only=1`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/list/{id}/tweetsAPI key

Get tweets from an X list

Latest tweets from a public list by numeric list id. Cursor-paginated.

Parameters

  • id · path · required · string

    Numeric list id

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • include_replies · query · boolean

    Include reply tweets (default false on /user/tweets, true elsewhere)

  • include_retweets · query · boolean

    Include retweets (default true)

  • media_only · query · boolean

    Only tweets that have media[] (default false)

  • since_id · query · string

    Keep tweets with id strictly greater than this snowflake (page filter; keep paging with cursor)

  • until_id · query · string

    Keep tweets with id strictly less than this snowflake (exclusive)

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/list/1539453138322673664/tweets?limit=20&include_replies=0&include_retweets=1&media_only=1`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/community/{id}/tweetsAPI key

Get tweets from an X community

Community timeline (CommunityTweetsTimeline). Cursor-paginated.

Parameters

  • id · path · required · string

    Numeric community id

  • ranking · query · string

    Relevance (default) or Recency (alias: rankingMode)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • include_replies · query · boolean

    Include reply tweets (default false on /user/tweets, true elsewhere)

  • include_retweets · query · boolean

    Include retweets (default true)

  • media_only · query · boolean

    Only tweets that have media[] (default false)

  • since_id · query · string

    Keep tweets with id strictly greater than this snowflake (page filter; keep paging with cursor)

  • until_id · query · string

    Keep tweets with id strictly less than this snowflake (exclusive)

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/community/1489422448332197888/tweets?ranking=Relevance&limit=20&include_replies=0&include_retweets=1&media_only=1`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/community/{id}API key

Get community metadata

Community name, description, member count, join policy (CommunityQuery).

Parameters

  • id · path · required · string

    Numeric community id

  • Response envelope: { data, meta }

Node.js

const res = await fetch(`${BASE}/v1/community/1489422448332197888`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/space/{id}API key

Get an X Space

Title, state, start time, listener counts, host/admins/speakers, and a listener sample (AudioSpaceById).

Parameters

  • id · path · required · string

    Space id from x.com/i/spaces/{id} (e.g. 1wxWjlvBZynJQ). Full space URLs are also accepted.

  • Response envelope: { data, meta }
  • state is running | ended | scheduled | canceled | unknown
  • listeners[] is a sample; compare listeners.length to listenerCount. Silent listeners are not a complete roster.
  • admins = hosts/co-hosts, speakers = on-stage guests

Node.js

const res = await fetch(`${BASE}/v1/space/1wxWjlvBZynJQ`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/space/{id}/usersAPI key

Get users in an X Space

Hosts, on-stage speakers, and a listener sample for a Space. Filter with role=admins|speakers|listeners|on_stage|all.

Parameters

  • id · path · required · string

    Space id (same as /v1/space/{id})

  • role · query · string

    all (default), admins, speakers, listeners, or on_stage (admins+speakers)

  • Response envelope: { data, next_cursor, cursor, meta } — snapshot, not cursor-paged
  • Each row: id, userName, name, profileImageUrl, isBlueVerified, role, joinedAt*
  • meta.listener_sample is true when listeners.length < listenerCount

Node.js

const res = await fetch(`${BASE}/v1/space/1wxWjlvBZynJQ/users?role=on_stage`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/broadcast/{id}API key

Get an X broadcast (live video)

Title, state, host, viewer counts, thumbnail, and start time for a live or replayable video broadcast.

Parameters

  • id · path · required · string

    Broadcast id from x.com/i/broadcasts/{id} (e.g. 1nxeLMkBVgYJX). Full broadcast URLs are also accepted.

  • Response envelope: { data, meta }
  • state is running | ended | scheduled | canceled | unknown
  • X does not expose a watcher roster — only watchingCount / watchedCount
  • host is the account running the stream

Node.js

const res = await fetch(`${BASE}/v1/broadcast/1nxeLMkBVgYJX`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/{id}API key

Get a tweet by id

Returns a single post with author, media[] (including altText and video variants[]), and engagement counts (likes, replies, retweets, quotes, bookmarks, views).

Parameters

  • id · path · required · string

    Numeric tweet/status id

  • Response envelope: { data, meta }
  • Cache-Control: private, max-age=60 (or CACHE_TTL_MS capped); weak ETag from tweet id; 304 on If-None-Match

Node.js

const res = await fetch(`${BASE}/v1/tweet/20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/by-urlAPI key

Get a tweet by X/Twitter URL

Accepts an x.com or twitter.com status URL (or raw numeric id) and returns the same shape as tweet-by-id.

Parameters

  • url · query · required · string

    Status URL (alias: u)

  • Response envelope: { data, meta }
  • Cache-Control: private, max-age=60 (or CACHE_TTL_MS capped); weak ETag from tweet id; 304 on If-None-Match

Node.js

const res = await fetch(`${BASE}/v1/tweet/by-url?url=https%3A%2F%2Fx.com%2Fjack%2Fstatus%2F20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/{id}/repliesAPI key

Get replies to a tweet

Conversation replies for a post (commenters + engagement). Cursor-paginated.

Parameters

  • id · path · required · string

    Numeric tweet/status id

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.
  • Parent tweet (when available) is in meta.tweet

Node.js

const res = await fetch(`${BASE}/v1/tweet/20/replies?limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/{id}/threadAPI key

Get thread context for a tweet

Parent chain (ancestors, oldest first), the focal tweet, and first-page replies from TweetDetail.

Parameters

  • id · path · required · string

    Numeric tweet/status id (any tweet in the thread)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, meta } with data.tweet, data.ancestors, data.replies
  • Pass meta.next_cursor as ?cursor= to page more replies
  • Missing parents are fetched up the inReplyTo chain (bounded)

Node.js

const res = await fetch(`${BASE}/v1/tweet/20/thread?limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/{id}/retweetersAPI key

List users who retweeted a tweet

Retweeters for a post. Cursor-paginated.

Parameters

  • id · path · required · string

    Numeric tweet/status id

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.
  • createdAt is the account join date. X does not expose when each user retweeted.

Node.js

const res = await fetch(`${BASE}/v1/tweet/20/retweeters?limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/{id}/likesAPI key

Like count for a tweet

Returns how many times a post was liked. X does not expose who liked it to these sessions. Same number as favoriteCount on GET /v1/tweet/{id}.

Parameters

  • id · path · required · string

    Numeric tweet/status id

  • Response envelope: { data, meta }
  • data: { id, likes }

Node.js

const res = await fetch(`${BASE}/v1/tweet/20/likes`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/{id}/quotesAPI key

List quote tweets of a tweet

Quote posts for a status via search (quoted_tweet_id). Cursor-paginated.

Parameters

  • id · path · required · string

    Numeric tweet/status id

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/tweet/20/quotes?limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/{id}/quotersAPI key

List users who quoted a tweet

Unique authors of quote tweets. Cursor-paginated (same cursor as /quotes).

Parameters

  • id · path · required · string

    Numeric tweet/status id

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.
  • quotedAt / quotedAtMs / quotedAtIso is when that user posted the quote tweet.

Node.js

const res = await fetch(`${BASE}/v1/tweet/20/quoters?limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/tweet/{id}/engagersAPI key

Build an engager pool / pick winners

Pages retweeters, reply authors, and/or quoters into a deduped pool. Optional random winners (TwitterPicker-style). Like identities are not available; use GET /v1/tweet/{id}/likes for the count.

Parameters

  • id · path · required · string

    Numeric tweet/status id

  • types · query · string

    Comma list: retweet,reply,quote (default retweet,reply,quote). like is accepted but skipped — identities are unavailable

  • mode · query · string

    union (any selected type) or intersect (all selected types)

  • max_pages · query · number

    Pages to pull per type (1-10, default 3)

  • limit · query · number

    Page size (1-40, default 20)

  • winners · query · number

    If set, data is a random sample of this size from the pool

  • seed · query · number

    Optional RNG seed for reproducible winner picks

  • Response envelope: { data, meta }
  • meta.counts has per-type and pool sizes; meta.notes explains skipped like identities
  • Without winners, data is the full deduped pool

Node.js

const res = await fetch(`${BASE}/v1/tweet/20/engagers?types=retweet%2Creply%2Cquote&mode=union&max_pages=3&limit=20&winners=5&seed=42`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
POST/v1/tweetsAPI key

Batch fetch tweets by id

Fetch up to 25 tweets in one request. Partial failures return in errors[].

Parameters

  • ids · body · required · string

    Array of tweet ids or status URLs (alias: tweetIds), max 25

  • Response envelope: { data, meta } with meta.errors / meta.max

Node.js

const res = await fetch(`${BASE}/v1/tweets`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "ids": [
      "20",
      "https://x.com/jack/status/20"
    ]
  }),
});
const data = await res.json();
console.log(data);
POST/v1/usersAPI key

Batch fetch user profiles

Fetch up to 25 profiles in one request by handle and/or numeric rest id. Partial failures return in errors[].

Parameters

  • userNames · body · string

    Array of handles without @ (alias: usernames)

  • userIds · body · string

    Array of numeric rest ids (alias: ids)

  • Response envelope: { data, meta } with meta.errors / meta.max
  • Each user includes currentSpace and currentBroadcast (live fleets lookup) or null

Node.js

const res = await fetch(`${BASE}/v1/users`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    "userNames": [
      "jack"
    ],
    "userIds": [
      "44196397"
    ]
  }),
});
const data = await res.json();
console.log(data);
GET/v1/user/followersAPI key

List followers for a user

Followers of an X account. Cursor-paginated.

Parameters

  • userName · query · required · string

    X handle without @ (alias: username)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/user/followers?userName=elonmusk&limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/user/followingAPI key

List accounts a user follows

Following list for an X account. Cursor-paginated.

Parameters

  • userName · query · required · string

    X handle without @ (alias: username)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/user/following?userName=elonmusk&limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/user/verified-followersAPI key

List verified followers for a user

Blue-verified followers only (BlueVerifiedFollowers). Cursor-paginated.

Parameters

  • userName · query · required · string

    X handle without @ (alias: username)

  • limit · query · number

    Page size (1-40, default 20)

  • cursor · query · string

    Opaque pagination cursor. Pass next_cursor (or cursor) from the previous response unchanged.

  • Response envelope: { data, next_cursor, cursor, meta }
  • meta.has_next_page mirrors next_cursor; extra context (user, filters, query) lives in meta
  • Pass next_cursor back as ?cursor=. Do not invent or parse cursors
  • Posts include createdAt (X date string), createdAtMs (unix ms), and createdAtIso (ISO-8601). On a retweet, createdAt is when it was reposted; retweetedStatus is the original post. Quotes expose quotedStatus the same way.

Node.js

const res = await fetch(`${BASE}/v1/user/verified-followers?userName=elonmusk&limit=20`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);
GET/v1/user/relationshipAPI key

Check follow relationship between two users

Whether source follows target and vice versa, via X friendships/show. Not scoped to the cookie owner.

Parameters

  • sourceUserName · query · string

    Source handle (alias: source). Provide handle or sourceUserId.

  • targetUserName · query · string

    Target handle (alias: target). Provide handle or targetUserId.

  • sourceUserId · query · string

    Source numeric rest id (alias: sourceId)

  • targetUserId · query · string

    Target numeric rest id (alias: targetId)

  • Response envelope: { data, meta }
  • data.source.following is true when source follows target
  • meta.source_follows_target / meta.target_follows_source mirror those flags

Node.js

const res = await fetch(`${BASE}/v1/user/relationship?sourceUserName=jack&targetUserName=elonmusk&sourceUserId=12&targetUserId=44196397`, {
  headers: {
    Authorization: `Bearer ${API_KEY}`,
  },
});
const data = await res.json();
console.log(data);

More formats