Published June 2026: reflects X's current pay-per-use pricing (including the April 2026 write-cost changes) and the official Python and TypeScript XDKs that X released in late 2025.
Key Takeaway: There are four practical ways to get Twitter/X data in Node.js in 2026: the official TypeScript XDK, the twitter-api-v2 library, plain fetch with a bearer token, or a read-only third-party REST API. The official routes bill per resource and require OAuth credentials; a key-only API suits read-heavy work.
If you searched "twitter api nodejs" expecting a quick npm install and a snippet that returns tweets, the 2026 landscape is messier than the old tutorials suggest. X changed its pricing model, changed how reads are billed, and, for the first time, shipped an official SDK for JavaScript. Most ranking Node guides still teach posting through a paid developer account and have not caught up to any of it.
We build and run Sorsa API, an alternative Twitter/X API, so the read-only path is the one we know best. It returns profiles, tweets, search results, and followers as clean JSON from a single fetch call, with one API key in the ApiKey header, no OAuth flow, and no developer-account approval to wait on. On read-heavy work it runs up to roughly 50x cheaper than the official X API, holds a flat 20 requests per second on every plan, and starts at $49 a month for 10,000 requests. Not every project fits that mold: some need to post, some need the official API for compliance, and some teams just want to understand the internals. This guide covers all four methods with working Node.js code, current pricing, and a complete collector that paginates and backs off on rate limits. You can also test calls without writing code in the playground.
Table of contents
- What changed: the X API and Node.js tooling in 2026
- The best library for the X API in Node.js
- Which approach should you use?
- Method 1: the official TypeScript XDK
- Method 2: twitter-api-v2
- Method 3: plain fetch with a bearer token
- Method 4: a read-only REST API
- Can you call the X API from the browser?
- Building a data collector in Node.js
- Comparison: four methods, side by side
- How to get your API credentials
- In practice: moving a Node collector off the official API
- FAQ
- Getting started
What Changed: the X API and Node.js Tooling in 2026
Three things changed for Node developers since 2023. The X API moved to pay-per-use billing with no free tier and now charges per resource read. Writing got more expensive after the April 2026 update. And X shipped its first official SDKs, including a TypeScript package that runs in Node, alongside the long-standing community library twitter-api-v2.
Pay-per-use is the default. There is no free tier and no $100 Basic plan for new signups. You buy credits upfront and pay per resource: $0.005 per post read, $0.010 per user profile, and $0.010 per follower or following record. Reading your own account's data costs $0.001 per resource, but that rate does not apply when you read other accounts. There is also a hard cap of 2 million post reads per month on standard accounts. For the full breakdown, see our X API pricing breakdown and the explainer on why X API pricing climbed.
Writing got more expensive. After the April 2026 update, a standard post costs $0.015 per request and a post that contains a URL costs $0.20. Follow, like, and quote-post actions were removed from the self-serve tiers and now require an Enterprise contract. A follow-back bot or an auto-liker is no longer possible on a standard pay-per-use account.
X released official SDKs. In late 2025 X announced first-party XDKs (X Developer Kit) for Python and TypeScript, confirmed in its developer announcement. The TypeScript XDK is the first official JavaScript client X has shipped. It wraps the v2 endpoints with typed models, handles pagination, and supports streaming.
twitter-api-v2 still works. The community library twitter-api-v2 supports both v1.1 and v2, runs read, write, and DM flows, and remains the most widely used Node wrapper. Existing code keeps working with current credentials.
Old libraries are dead. The twit and twitter packages on npm have not seen meaningful updates since 2017 and only speak v1.1. If a tutorial tells you to npm install twit, it is outdated.
The Best Library for the X API in Node.js
For most Node projects, twitter-api-v2 is the best general-purpose library: it is mature, fully typed, and supports read, write, and DM flows through bearer-token and OAuth. If you want a first-party tool that tracks the API spec exactly, use the official TypeScript XDK. For read-only data collection, many teams skip libraries and call a third-party REST API with plain fetch, which removes OAuth entirely.
Here is how the main options compare.
| Library / tool | Type | Best for | Notes |
|---|---|---|---|
| Official TypeScript XDK | Official | New builds, first-party support | Typed, auto-pagination, streaming, runs in Node, browsers, and React Native. Young (v0.5, Feb 2026). Needs paid X credentials. |
| twitter-api-v2 | Community | General integration, bots, scripts | Mature, typed, read/write/DM clients, handles pagination and rate-limit retries. Needs paid X credentials. |
| twit / twitter | Community | Avoid | Unmaintained since 2017, v1.1 only. |
| fetch / axios (no wrapper) | Standard | Minimal dependencies, custom clients | You build pagination and error handling. Pairs well with a third-party API. |
| Read-only REST API | Third-party | Read-heavy data collection | One key in a header, no OAuth, flat per-request billing. Read-only. |
Every option that targets the official API bills through X's pay-per-use pricing, so the cost is identical whether you call X with the XDK, twitter-api-v2, or raw fetch. The variable you actually control is how many resources you pull, which is where batch endpoints and a flat-rate API change the math.
Which Approach Should You Use?
Pick the path before writing code. For read-and-write work with official support, use the XDK or twitter-api-v2. For read-only data at volume with minimal setup, a third-party REST API removes OAuth and the approval queue. For full control with no dependencies, plain fetch plus a bearer token works. The choice is mostly read-versus-write and how much volume you pull.
| If you need... | Use... |
|---|---|
| Read and write with full official support | Official XDK or twitter-api-v2 |
| Read-only data at scale, minimal setup | A read-only third-party REST API |
| Full control over HTTP, zero dependencies | Plain fetch plus a bearer token |
| To post, or to follow / like (Enterprise) | Official XDK or twitter-api-v2 (OAuth required) |
If your project only reads public data, a third-party API removes the OAuth dance: one key in a header and you start pulling data, with no developer-account application and no credit purchase. If you need to post or run write actions, the official X API through the XDK or twitter-api-v2 is the path; no third-party provider posts on your behalf. Working in Python instead? See the Python version of this guide.
Method 1: the Official TypeScript XDK
The TypeScript XDK is X's first official JavaScript SDK. It wraps the v2 API with typed models, handles pagination, supports streaming, and works in Node.js, browsers, and React Native. It requires Node.js 16 or newer and supports bearer-token, OAuth 2.0 PKCE, and OAuth 1.0a authentication.
Install it:
npm install @xdevplatform/xdk
A bearer token is enough to read public data. Look up a profile:
import { Client } from "@xdevplatform/xdk";
// App-only auth: a bearer token covers read-only access to public data
const client = new Client({ bearerToken: process.env.X_API_BEARER_TOKEN });
async function main() {
const user = await client.users.getByUsername("elonmusk");
console.log(user.data?.username, user.data?.name);
}
main();
The SDK ships a paginator for list endpoints. Pull a user's followers with automatic paging:
import { Client, UserPaginator } from "@xdevplatform/xdk";
const client = new Client({ bearerToken: process.env.X_API_BEARER_TOKEN });
const followers = new UserPaginator(async (token) => {
const res = await client.users.getFollowers("44196397", {
maxResults: 100,
paginationToken: token,
userfields: ["id", "name", "username"],
});
return { data: res.data ?? [], meta: res.meta, includes: res.includes, errors: res.errors };
});
for await (const follower of followers) {
console.log(follower.username);
}
The XDK also exposes client.posts for search and timelines and client.stream for real-time feeds. It is the right pick when you want official support, need write access, and are starting a new build. The tradeoffs: the SDK is young (v0.5 as of February 2026), the docs are still thin, and you pay X's per-resource pricing on every call.
Method 2: twitter-api-v2
twitter-api-v2 has been the default Node client for years. It supports v1.1 and v2, exposes separate read-only, read-write, and DM clients, and handles pagination and rate-limit headers. It is the closest Node equivalent to Tweepy in Python.
Install it from npm:
npm install twitter-api-v2
Create a read-only client from a bearer token and look up a profile:
import { TwitterApi } from "twitter-api-v2";
const client = new TwitterApi(process.env.X_API_BEARER_TOKEN).readOnly;
const user = await client.v2.userByUsername("elonmusk", {
"user.fields": ["description", "public_metrics", "created_at"],
});
console.log(user.data.username, user.data.public_metrics?.followers_count);
Search the last 7 days. The search method returns a paginator you can iterate directly:
const search = await client.v2.search("nodejs lang:en", {
max_results: 20,
"tweet.fields": ["created_at", "public_metrics"],
});
for await (const tweet of search) {
console.log(tweet.text);
}
Fetch a user's followers as a paginator:
const followers = await client.v2.followers("44196397", { asPaginator: true });
for await (const follower of followers) {
console.log(follower.username);
}
twitter-api-v2 is the safe default for most Node developers: battle-tested, well documented, and with an answer for almost any issue. The tradeoffs match the XDK: you still need a paid X developer account, you still pay per resource, and rate limits are inherited from the official API (typically 300 to 900 requests per 15-minute window, depending on the endpoint).
Method 3: plain fetch With a Bearer Token
No library, no wrapper. Node 18 and newer ship a global fetch, so you can call the X API v2 directly with a bearer token and zero dependencies. This suits developers who want full control over requests, or who work where installing packages is restricted.
Search for recent tweets:
// Node 18+ has global fetch, so no dependencies are needed
const headers = { Authorization: `Bearer ${process.env.X_API_BEARER_TOKEN}` };
const url = new URL("https://api.x.com/2/tweets/search/recent");
url.searchParams.set("query", "nodejs lang:en");
url.searchParams.set("max_results", "20");
url.searchParams.set("tweet.fields", "created_at,public_metrics");
const res = await fetch(url, { headers });
const data = await res.json();
for (const tweet of data.data ?? []) {
console.log(tweet.text);
}
The official API paginates with a next_token in the response meta. Page through every result with a guard so a broad query does not run away:
async function searchAll(query, maxPages = 10) {
const headers = { Authorization: `Bearer ${process.env.X_API_BEARER_TOKEN}` };
const all = [];
let nextToken;
let pages = 0;
do {
const url = new URL("https://api.x.com/2/tweets/search/recent");
url.searchParams.set("query", query);
url.searchParams.set("max_results", "100");
if (nextToken) url.searchParams.set("next_token", nextToken);
const res = await fetch(url, { headers });
const data = await res.json();
all.push(...(data.data ?? []));
nextToken = data.meta?.next_token;
pages += 1;
} while (nextToken && pages < maxPages);
return all;
}
This works when you want minimal dependencies or you are debugging API behavior. The downside is obvious: you handle pagination, error codes, rate limiting, and retries yourself. For a production pipeline you will end up rebuilding a wrapper. This method still needs an X developer account and pay-per-use credits, with a bearer token for read-only access.
Method 4: a Read-Only REST API
If a project only reads public Twitter data, a third-party REST API skips the official API entirely: no OAuth, no application step, no credit-purchase workflow, just one key in a header and JSON back. For a read-only workload, it removes most of the official API's setup and turns data collection into plain HTTP calls.
This is the practical route to getting X data without a developer account. Here is what it looks like with Sorsa, using nothing but fetch.
Get a user profile:
const headers = { ApiKey: process.env.SORSA_API_KEY };
const res = await fetch("https://api.sorsa.io/v3/info?username=elonmusk", { headers });
const user = await res.json();
console.log(`@${user.username}: ${user.display_name}`);
console.log(`Followers: ${user.followers_count}`);
Search tweets with the full web operator set. The search endpoint returns about 20 tweets per page and a next_cursor for the next page:
const res = await fetch("https://api.sorsa.io/v3/search-tweets", {
method: "POST",
headers: { ApiKey: process.env.SORSA_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ query: "nodejs lang:en", order: "latest" }),
});
const { tweets, next_cursor } = await res.json();
for (const tweet of tweets) {
console.log(`${tweet.likes_count} likes: ${tweet.full_text}`);
}
For complex queries, combine operators the same way you would in advanced search; the full list is in our search operator reference, and the endpoint searches the full tweet archive rather than only the last 7 days. There is a dedicated guide to searching tweets via API if you want the deep version.
Pull a follower list. One request returns up to 200 profiles:
const headers = { ApiKey: process.env.SORSA_API_KEY };
const res = await fetch("https://api.sorsa.io/v3/followers?username=elonmusk", { headers });
const { users, next_cursor } = await res.json();
console.log(`Got ${users.length} followers in one request`);
Fetch up to 100 tweets in a single call with the bulk endpoint, which returns complete tweet objects (metrics and author included) and counts as one request:
const res = await fetch("https://api.sorsa.io/v3/tweet-info-bulk", {
method: "POST",
headers: { ApiKey: process.env.SORSA_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({
tweet_links: ["1782368585664626774", "1782368585664626775"],
}),
});
const { tweets } = await res.json();
Every tweet response carries the full author profile and the public metrics (likes_count, retweet_count, reply_count, quote_count, view_count), so reading tweet metrics via API and fetching follower lists costs no extra calls. The header is ApiKey, the base URL is https://api.sorsa.io/v3, and the response shapes match the API documentation exactly.
Can You Call the X API From the Browser?
No. You cannot safely call the X API directly from client-side JavaScript, because every authenticated request needs a bearer token or OAuth secret, and anything in browser code is visible to anyone who opens dev tools. Calls also fail cross-origin in most cases. The standard fix is a small server-side proxy that holds the credentials and exposes only the data your front end needs.
The shape is simple. A serverless function on Vercel, Cloudflare Workers, Netlify, or any host reads the secret from an environment variable, calls the API server-side, and returns clean JSON to the browser:
// /api/tweets (serverless function, runs on the server, not in the browser)
export default async function handler(req, res) {
const r = await fetch("https://api.sorsa.io/v3/search-tweets", {
method: "POST",
headers: { ApiKey: process.env.SORSA_API_KEY, "Content-Type": "application/json" },
body: JSON.stringify({ query: req.query.q, order: "latest" }),
});
const data = await r.json();
res.status(200).json(data);
}
The browser then calls your own /api/tweets endpoint, never the data provider, and the key never leaves the server. The official TypeScript XDK technically runs in the browser and React Native, but that does not change the rule: shipping a bearer token to client code exposes it, so keep credentials behind a server endpoint regardless of which client you use.
Building a Data Collector in Node.js
A production collector needs three things beyond a single call: cursor pagination to walk past the first page, a page guard so a broad query does not exhaust your quota, and a retry on rate limits. Here is a complete read-only collector against the search endpoint, paginating with next_cursor and backing off on a 429.
async function collectTweets(query, maxPages = 20) {
const endpoint = "https://api.sorsa.io/v3/search-tweets";
const headers = { ApiKey: process.env.SORSA_API_KEY, "Content-Type": "application/json" };
const collected = [];
let cursor;
let pages = 0;
while (pages < maxPages) {
const body = { query, order: "latest" };
if (cursor) body.next_cursor = cursor;
const res = await fetch(endpoint, {
method: "POST",
headers,
body: JSON.stringify(body),
});
// Flat 20 requests per second limit: on a 429, wait a second and retry the same page
if (res.status === 429) {
await new Promise((r) => setTimeout(r, 1000));
continue;
}
const data = await res.json();
collected.push(...(data.tweets ?? []));
cursor = data.next_cursor;
pages += 1;
if (!cursor) break;
}
return collected;
}
// Usage
const tweets = await collectTweets("from:OpenAI -is:retweet");
console.log(`Collected ${tweets.length} tweets`);
When we rebuilt our own collectors against the search endpoint, the variable that actually mattered was not the library but how many resources each call returned and how billing reacted to that. A flat per-request limit is simpler to pace against than per-endpoint windows: you wait one second on a 429 instead of tracking a reset timestamp. The mechanics of cursors are covered in the pagination guide, and the official side is in our X API rate limits reference. The same loop swaps cleanly onto /user-tweets, /followers, or /mentions by changing the endpoint and body.
Comparison: Four Methods, Side by Side
The four methods split cleanly on two axes: whether you can write, and how you are billed. All three official-API routes need a developer account and bill per resource. A read-only API trades write access for a single key and flat per-request billing.
| Method | Setup | Auth | Reads | Writes | Billing |
|---|---|---|---|---|---|
| Official TypeScript XDK | Developer account, credits | Bearer / OAuth 2.0 / OAuth 1.0a | Yes | Yes (posts; follow, like, quote on Enterprise) | Per resource |
| twitter-api-v2 | Developer account, credits | Bearer / OAuth | Yes | Yes | Per resource |
| Plain fetch | Developer account, credits | Bearer / OAuth | Yes | Yes | Per resource |
| Read-only REST API | API key, about 3 minutes | Single ApiKey header | Yes | No (read-only) | Flat per request |
The split tells you which to pick: if you need to post or run write actions, that is the official API's territory through the XDK or twitter-api-v2. For read-heavy access at a flat, predictable price, a read-only API is the cheaper and simpler route, and it returns the same public data.
The cost gap on reads comes entirely from the billing unit. The official API charges for every post and every author profile in a response; a flat-rate API charges one request regardless of how many items it returns.
| Workload | Official X API | Read-only API (Sorsa Pro) |
|---|---|---|
| Search returning 20 tweets, with author data | $0.30 (20 x $0.005 plus 20 x $0.010) | One request, about $0.002 (authors included) |
| 1,000 follower profiles | About $10 (per profile) | About $0.01 (5 requests at 200 per page) |
| 100 tweets by ID, with author data | $1.50 (100 x $0.005 plus 100 x $0.010) | One request, about $0.002 (bulk endpoint) |
| Monthly cap | 2 million post reads | Plan based (10,000 to 500,000 requests) |
| Rate limit | 300 to 900 per 15 minutes (varies) | 20 requests per second, flat |
For read-heavy work the per-resource model is the expensive way to do a simple job, which is why the flat per-request rate wins once you cross roughly 10,000 reads a month. Writes are the exception: posting and DMs live only on the official API, so a write-heavy project belongs there regardless of read cost.
How to Get Your API Credentials
For the official API, create a developer account at developer.x.com, agree to the developer terms, describe your use case, and create a Project and App to generate an API key, an API secret, a bearer token, and access tokens. Buy credits before your first call, since there is no free tier. For a read-only third-party API, sign up, generate a key, and pass it in a header, with no application or approval step.
Store either credential in an environment variable, never in source:
# .env
X_API_BEARER_TOKEN=your-x-bearer-token
SORSA_API_KEY=your-sorsa-api-key
If you are moving existing official-API code over, the migration guide maps the official endpoints and field names to their flat-rate equivalents so you can swap the transport without rewriting the logic.
In Practice: Moving a Node Collector Off the Official API
A roughly 12-person social analytics startup came to us running a nightly Node collector built on twitter-api-v2. The code was fine; the bill was not. Every run paid per post read and per author profile, and the 2-million-post-reads monthly cap forced the team to watch volume as its tracked-account list grew.
The fix was a transport swap, not a rewrite. They kept the collection logic and the scheduling, replaced the twitter-api-v2 client with the plain fetch pattern against the search and /followers endpoints, and dropped OAuth for a single ApiKey header. Because each request returns up to 20 tweets or 200 follower profiles instead of billing per resource, the same nightly pull cost a fraction of what it had, roughly 30 to 50 times less on the read-heavy parts, and a per-second limit replaced the monthly cap as the only thing to pace against. For a read-only workload, the per-resource model had been the expensive way to do a simple job.
FAQ
Is there an official Twitter API SDK for Node.js?
Yes. In late 2025 X released an official TypeScript XDK, installed with npm install @xdevplatform/xdk, that runs in Node.js, browsers, and React Native. It is the first official JavaScript client X has shipped, with typed models, automatic pagination, and streaming. The mature community library twitter-api-v2 remains a strong alternative and supports both API v1.1 and v2.
What is the best npm package for the Twitter API?
For most Node projects, twitter-api-v2 is the best general-purpose choice: it is mature, fully typed, supports read, write, and DM flows, and handles pagination and rate-limit retries. For first-party support that tracks the API spec, use the official TypeScript XDK. The old twit and twitter packages are unmaintained since 2017 and speak only API v1.1, so avoid them.
Can you use the Twitter API in client-side JavaScript?
No, not directly. Every authenticated X API call needs a bearer token or OAuth secret, and any credential placed in browser code is exposed to anyone who inspects the page, plus most calls fail cross-origin. The standard pattern is a small server-side proxy, such as a serverless function, that holds the secret, calls the API, and returns only the data your front end needs.
How do you get tweets in Node.js without a developer account?
Call a read-only third-party REST API. With Sorsa, you sign up, get an API key, pass it in the ApiKey header, and POST a query to the search endpoint, all from a single fetch call. There is no OAuth flow, no app review, and no credit purchase, and the JSON maps straight to JavaScript objects with the author profile included in each tweet.
How much does the Twitter API cost for a Node.js app in 2026?
On the official X API you pay per resource: $0.005 per post read, $0.010 per user profile, $0.015 per standard post, and $0.20 for a post with a URL, with a 2 million post reads monthly cap. A search returning 20 tweets costs $0.30 once author profiles are included. Sorsa bills per request on flat plans from $49 a month for 10,000 requests, and each request returns up to 20 tweets or 200 follower profiles.
How do you handle Twitter API rate limits in Node.js?
The official API limits requests per 15-minute window (typically 300 to 900 depending on the endpoint) and returns a 429 with a reset header when you hit one. twitter-api-v2 and the XDK back off automatically; with plain fetch you read the headers and wait before retrying. A flat-rate API like Sorsa uses a per-second limit (20 requests per second), so on a 429 you wait one second and retry the same call.
Does twitter-api-v2 support the X API v2?
Yes. twitter-api-v2 supports both API v1.1 and v2, with separate read-only, read-write, and DM clients and full TypeScript typings. It works with current bearer-token and OAuth authentication. It does require a paid X developer account with purchased credits, since there is no free tier on the official API under the pay-per-use model.
Getting Started
Pick a method and run one of the examples above.
- Read-only data: grab a key from the Sorsa dashboard, set it as
SORSA_API_KEY, and run any Method 4 snippet. Structured X data lands in your terminal in under a minute, and the quickstart walks through the first call. Plans and limits are on the pricing page. - Read and write: create a developer account at developer.x.com, buy credits, and run the XDK or twitter-api-v2 examples with your bearer token.
- Comparing providers: for a broader look at read-only options, see the Twitter API alternatives comparison.
Reviewed by Keksich, founder of Sorsa, marketer and X API researcher.
How We Verified This Guide
We wrote and verified this guide in June 2026 while operating the API daily. The official XDK details (the @xdevplatform/xdk package, Node.js 16+ support, automatic pagination, streaming, and the three authentication methods) come from X's TypeScript XDK documentation and its launch announcement. The twitter-api-v2 capabilities (the read-only, read-write, and DM clients, and the userByUsername, search, and followers methods) were checked against its package documentation. X API pricing reflects the current pay-per-use model including the April 2026 write-cost changes. Sorsa endpoint behavior, per-request batching, and plan pricing come from the Sorsa API documentation; more about the team is on our About page. Numbers that move, such as download counts and GitHub stars, are described rather than cited; for a current price the in-product docs are the source of truth.