x-twitter-scraper
X API & Twitter API SDK for TypeScript. Scrape Twitter search, profiles & followers as a Twitter scraper & tweet scraper. Not affiliated with X Corp.
Package details
Install x-twitter-scraper from npm and Pi will load the resources declared by the package manifest.
$ pi install npm:x-twitter-scraper- Package
x-twitter-scraper- Version
0.13.3- Published
- Oct 14, 2026
- Downloads
- 678/mo · 103/wk
- Author
- burakbayir
- License
- Apache-2.0
- Types
- skill
- Size
- 4.7 MB
- Dependencies
- 0 dependencies · 0 peers
Pi manifest JSON
{
"image": "https://raw.githubusercontent.com/Xquik-dev/x-twitter-scraper-typescript/main/assets/pi-package.png",
"skills": [
"./skills"
]
}Security note
Pi packages can execute code and influence agent behavior. Review the source before installing third-party packages.
README
X API & Twitter API TypeScript SDK by Xquik
Use this X API & Twitter API SDK to work with X from TypeScript. It works as a Twitter scraper & tweet scraper for search, profiles & followers. Scrape Twitter timelines, lists, communities, Spaces & trends into typed results. Manage media, webhooks, monitors & X automation with bundled agent Skills. It provides a Twitter API alternative through documented Xquik REST routes.
Xquik is the world's fastest and cheapest X Twitter scraper service with the most complete X data. Xquik charges only for delivered, unique, filter-matching results and never pads rows.
Xquik is an independent third-party service. Not affiliated with X Corp. "Twitter" and "X" are trademarks of X Corp.
TypeScript SDK guide | API map | REST API | Webhooks | MCP guide
Pi coding agent package
Install the bundled Xquik Skills from npm.
pi install npm:x-twitter-scraper
Pi loads 3 packaged Skills.
x-twitter-scraperfor API and MCP integration.xquik-social-researchfor public X research.xquik-account-automationfor approved connected-account actions.
Import the typed SDK from the same npm package.
Common Twitter & X tasks
| Task | REST route | Usage |
|---|---|---|
| Search tweets without the X API | GET /x/tweets/search |
Use keyword or advanced operator queries. |
| Read an X profile timeline | GET /x/users/{id}/tweets |
Paginate bounded results. |
| Scrape Twitter followers | GET /x/users/{id}/followers |
Use an extraction for complete datasets. |
| Scrape following accounts | GET /x/users/{id}/following |
Use an extraction for complete datasets. |
| Read a home timeline | GET /x/timeline |
Approve this private read. |
| Export large X datasets | POST /extractions |
Poll status, then download results. |
| Download or upload media | /x/media/* |
Use typed file helpers. |
| Monitor an account | POST /monitors |
Deliver events through HMAC webhooks. |
| Run a giveaway draw | POST /draws |
Confirm the tweet and entry rules. |
| Post or reply | POST /x/tweets |
Confirm the account and payload. |
AI agent workflows with MCP
Use the typed REST SDK in application code. Add https://xquik.com/mcp to MCP clients.
Follow the MCP guide for current authentication support.
Package & registry trust
- npm package
x-twitter-scraper - Source in Xquik-dev/x-twitter-scraper-typescript
- Apache-2.0 license for the SDK
- MIT license for the bundled Skills
- Citation metadata in CITATION.cff
- Security boundary and reporting in SECURITY.md
- OpenSSF evidence and current limitations in OPENSSF.md
Installation
The SDK requires TypeScript 4.9 or later.
npm install x-twitter-scraper
Usage
See api.md for the complete API.
import XTwitterScraper from 'x-twitter-scraper';
const client = new XTwitterScraper({
apiKey: process.env['X_TWITTER_SCRAPER_API_KEY'], // Optional. The client reads this variable.
});
const response = await client.x.tweets.search({ q: 'from:elonmusk', limit: 10 });
Request & response types
The package includes types for every request parameter and response field. Import them directly.
import XTwitterScraper from 'x-twitter-scraper';
const client = new XTwitterScraper({
apiKey: process.env['X_TWITTER_SCRAPER_API_KEY'], // Optional. The client reads this variable.
});
const params: XTwitterScraper.X.TweetSearchParams = { q: 'from:elonmusk', limit: 10 };
const paginatedTweets: XTwitterScraper.PaginatedTweets = await client.x.tweets.search(params);
Editors show each method, parameter, and field description from its docstring.
Guest wallet authentication
Guest wallet keys work through the public Bearer flow. Pass the key through the
bearerToken option, then poll status or create a confirmed top-up checkout.
const guestClient = new XTwitterScraper({
bearerToken: process.env['XQUIK_GUEST_API_KEY'],
});
const wallet = await guestClient.guestWallets.retrieveStatus();
Keep guest keys out of source code, URLs, and logs.
Streaming events
client.events.stream() yields each monitor event as it happens.
const stream = await client.events.stream();
for await (const event of stream) {
console.log(event.type, event.id);
}
Pass { 'Last-Event-ID': '42' } to resume after event 42.
Break out of the loop or call stream.controller.abort() to close the stream.
File uploads
Pass file uploads in these forms.
File(or an object with the same structure)- a
fetchResponse(or an object with the same structure) - an
fs.ReadStream - the return value of our
toFilehelper
import fs from 'fs';
import XTwitterScraper, { toFile } from 'x-twitter-scraper';
const client = new XTwitterScraper();
// Stream a local file with Node fs.
await client.x.media.upload({ account: '@elonmusk', file: fs.createReadStream('/path/to/file') });
// Pass a web File.
await client.x.media.upload({ account: '@elonmusk', file: new File(['my bytes'], 'file') });
// Pass a fetch Response.
await client.x.media.upload({ account: '@elonmusk', file: await fetch('https://somesite/file') });
// Convert bytes with toFile.
await client.x.media.upload({
account: '@elonmusk',
file: await toFile(Buffer.from('my bytes'), 'file'),
});
await client.x.media.upload({
account: '@elonmusk',
file: await toFile(new Uint8Array([0, 1, 2]), 'file'),
});
Handling errors
The SDK throws an APIError subclass for connection failures and non-2xx responses.
const paginatedTweets = await client.x.tweets
.search({ q: 'from:elonmusk', limit: 10 })
.catch(async (err) => {
if (err instanceof XTwitterScraper.APIError) {
console.log(err.status); // 400
console.log(err.name); // BadRequestError
console.log(err.headers); // {server: 'nginx', ...}
} else {
throw err;
}
});
| Status code | Error type |
|---|---|
| 400 | BadRequestError |
| 401 | AuthenticationError |
| 403 | PermissionDeniedError |
| 404 | NotFoundError |
| 422 | UnprocessableEntityError |
| 429 | RateLimitError |
| >=500 | InternalServerError |
| N/A | APIConnectionError |
Retries
The SDK retries connection errors and HTTP 408, 409, 429, and 5xx responses. It uses exponential backoff and attempts 2 retries by default.
Set maxRetries to change or disable retries.
// Change the default for all requests.
const client = new XTwitterScraper({
maxRetries: 0,
});
// Override one request.
await client.x.tweets.search({ q: 'from:elonmusk', limit: 10 }, {
maxRetries: 5,
});
Timeouts
Requests time out after 1 minute. Set a custom timeout when needed.
// Change the default for all requests.
const client = new XTwitterScraper({
timeout: 20 * 1000,
});
// Override one request.
await client.x.tweets.search({ q: 'from:elonmusk', limit: 10 }, {
timeout: 5 * 1000,
});
On timeout, the SDK throws an APIConnectionTimeoutError.
Timed-out requests follow the default retry policy.
Raw response data
Call .asResponse() on any returned APIPromise to access the raw fetch() response.
It returns after receiving successful headers without consuming the body.
Then parse or stream the body.
Call .withResponse() to receive the raw response and parsed data together.
This method consumes and parses the body before returning.
const client = new XTwitterScraper();
const response = await client.x.tweets.search({ q: 'from:elonmusk', limit: 10 }).asResponse();
console.log(response.headers.get('X-My-Header'));
console.log(response.statusText); // access the underlying Response object
const { data: paginatedTweets, response: raw } = await client.x.tweets
.search({ q: 'from:elonmusk', limit: 10 })
.withResponse();
console.log(raw.headers.get('X-My-Header'));
console.log(paginatedTweets.has_next_page);
Logging
[!IMPORTANT] Log messages are for debugging only. The format and content of log messages may change between releases.
Log levels
Configure the log level in 2 ways.
- Set the
X_TWITTER_SCRAPER_LOGenvironment variable. - Set the
logLevelclient option. It overrides the environment variable.
import XTwitterScraper from 'x-twitter-scraper';
const client = new XTwitterScraper({
logLevel: 'debug', // Show all log messages
});
These are the log levels, from most to least verbose.
'debug'shows debug messages, info, warnings, and errors.'info'shows info messages, warnings, and errors.'warn'shows warnings and errors. It is the default.'error'shows only errors.'off'disables all logging.
At the 'debug' level, the SDK logs every HTTP request and response, including headers and bodies.
It redacts some authentication headers, but request and response bodies may still show sensitive data.
Custom logger
The SDK logs through globalThis.console by default. Pass a custom logger instead.
It supports pino, winston, bunyan, consola, signale, and @std/log.
The logLevel option still controls custom logger output.
import XTwitterScraper from 'x-twitter-scraper';
import pino from 'pino';
const logger = pino();
const client = new XTwitterScraper({
logger: logger.child({ name: 'XTwitterScraper' }),
logLevel: 'debug', // Send all messages to pino, allowing it to filter
});
Custom requests
The SDK types every documented endpoint, parameter, and response property. Use its lower-level methods for undocumented API features.
Undocumented endpoints
Use client.get, client.post, or another HTTP method for undocumented endpoints.
Client options, including retries, apply to these requests.
await client.post('/some/path', {
body: { some_prop: 'foo' },
query: { some_query_arg: 'bar' },
});
Undocumented request params
Add // @ts-expect-error to an undocumented parameter.
The SDK sends extra values without runtime type validation.
client.x.tweets.search({
// ...
// @ts-expect-error baz is not yet public
baz: 'undocumented option',
});
The SDK sends extra GET parameters in the query.
It sends all other extra parameters in the body.
Send explicit extra arguments through the query, body, and headers options.
Undocumented response properties
Add // @ts-expect-error to the response object or cast it to the required type.
The SDK does not validate or remove extra API response properties.
Custom fetch client
The SDK uses the global fetch function by default.
Polyfill the global to use another fetch implementation.
import fetch from 'my-fetch';
globalThis.fetch = fetch;
Or pass it to the client.
import XTwitterScraper from 'x-twitter-scraper';
import fetch from 'my-fetch';
const client = new XTwitterScraper({ fetch });
Fetch options
Set fetchOptions on the client or request without replacing fetch. Request options take precedence.
import XTwitterScraper from 'x-twitter-scraper';
const client = new XTwitterScraper({
fetchOptions: {
// `RequestInit` options
},
});
Proxies
Add runtime-specific proxy settings through fetchOptions.
Node [docs]
import XTwitterScraper from 'x-twitter-scraper';
import * as undici from 'undici';
const proxyAgent = new undici.ProxyAgent('http://localhost:8888');
const client = new XTwitterScraper({
fetchOptions: {
dispatcher: proxyAgent,
},
});
Bun [docs]
import XTwitterScraper from 'x-twitter-scraper';
const client = new XTwitterScraper({
fetchOptions: {
proxy: 'http://localhost:8888',
},
});
Deno [docs]
import XTwitterScraper from 'npm:x-twitter-scraper';
const httpClient = Deno.createHttpClient({ proxy: { url: 'http://localhost:8888' } });
const client = new XTwitterScraper({
fetchOptions: {
client: httpClient,
},
});
Semantic versioning
This package follows SemVer with these exceptions.
- Static type changes that preserve runtime behavior.
- Changes to undocumented internals that remain technically public.
- Changes unlikely to affect normal use.
Open an issue with questions, bugs, or suggestions.
Runtime support
The SDK supports these runtimes.
- Current Chrome, Firefox, Safari, Edge, and other web browsers.
- Maintained Node.js 20 LTS or later.
- Deno v1.28.0 or later.
- Bun 1.0 or later.
- Cloudflare Workers.
- Vercel Edge Runtime.
- Jest 28 or later with the
"node"environment, not"jsdom". - Nitro v2.6 or later.
The SDK does not support React Native.
Request another runtime in a GitHub issue.
Contributing
See the contributing documentation.
Xquik is an independent third-party service. Not affiliated with X Corp. "Twitter" and "X" are trademarks of X Corp.
