Skip to main content

X API & Twitter API Python SDK by Xquik

OpenSSF Best Practices

PyPI version

Scrape Twitter from Python with this X API & Twitter API alternative. It is a typed Twitter scraper & tweet scraper for Python 3.10 & later. Use the Xquik Python SDK for Twitter search, timelines, profiles & followers. Manage media, webhooks & X automation 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.

Python SDK guide | API map | REST API | Webhooks | MCP guide

Trust & usage

Twitter API package downloads Twitter scraper users on Apify Twitter scraper runs on Apify Tweet scraper rating on Apify Xquik Twitter API accounts Twitter Skill installs Xquik verified revenue on TrustMRR Twitter API median response time Xquik GitHub stars x-twitter-scraper downloads on PyPI OpenSSF Best Practices

  • 51,000+ downloads of Xquik's Twitter API packages on npm, PyPI, RubyGems, NuGet, Packagist & Terraform (source)
  • 7,800+ users of Xquik's Twitter scraper Actors on Apify (source)
  • 5,700,000+ runs of Xquik's Twitter scraper Actors on Apify (source)
  • 4.66 of 5 for the X Tweet Scraper from 16 Apify reviews (source)
  • 3,900+ accounts on xquik.com (source)
  • 1,600+ installs of Xquik's Twitter Skills on skills.sh (source)
  • $38,000+ in revenue verified by TrustMRR (source)
  • 501 ms median REST API read time over the last 7 days (source)
  • 370+ GitHub stars across Xquik's repos (source)
  • 3,400+ downloads of x-twitter-scraper on PyPI (source)
  • This repo meets the OpenSSF Best Practices passing criteria (source)

Checked on 2026-10-15. See each number with its date & source on xquik.com/trust or as JSON.

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.
Run giveaway draws POST /draws Pick winners from post replies.
Download or upload media /x/media/* Use typed file helpers.
Monitor an account POST /monitors Deliver events through HMAC webhooks.
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

Installation

pip install x_twitter_scraper

Usage

See api.md for the complete API.

import os
from x_twitter_scraper import XTwitterScraper

client = XTwitterScraper(
    api_key=os.environ.get("X_TWITTER_SCRAPER_API_KEY"),  # Optional. The client reads this variable.
)

response = client.x.tweets.search(
    q="from:elonmusk",
    limit=10,
)

Pass api_key directly or load X_TWITTER_SCRAPER_API_KEY with python-dotenv. Keep credentials out of source control.

Async usage

Import AsyncXTwitterScraper and await each API call.

import os
import asyncio
from x_twitter_scraper import AsyncXTwitterScraper

client = AsyncXTwitterScraper(
    api_key=os.environ.get("X_TWITTER_SCRAPER_API_KEY"),  # Optional. The client reads this variable.
)


async def main() -> None:
    response = await client.x.tweets.search(
        q="from:elonmusk",
        limit=10,
    )


asyncio.run(main())

Both clients expose the same resources and methods.

With aiohttp

The async client uses httpx. Install aiohttp for an alternative backend.

pip install x_twitter_scraper[aiohttp]

Select it with http_client=DefaultAioHttpClient().

import os
import asyncio
from x_twitter_scraper import DefaultAioHttpClient
from x_twitter_scraper import AsyncXTwitterScraper


async def main() -> None:
    async with AsyncXTwitterScraper(
        api_key=os.environ.get("X_TWITTER_SCRAPER_API_KEY"),  # Optional. The client reads this variable.
        http_client=DefaultAioHttpClient(),
    ) as client:
        response = await client.x.tweets.search(
            q="from:elonmusk",
            limit=10,
        )


asyncio.run(main())

Using types

Nested request parameters use TypedDicts. Responses use Pydantic models with these helpers.

  • Serialize to JSON with model.to_json().
  • Convert to a dictionary with model.to_dict().

Set python.analysis.typeCheckingMode to basic in VS Code to catch type errors.

File uploads

Pass uploads as bytes, a PathLike, or (filename, contents, media_type).

from pathlib import Path
from x_twitter_scraper import XTwitterScraper

client = XTwitterScraper()

client.x.media.upload(
    account="@elonmusk",
    file=Path("/path/to/file"),
)

The async client uses the same interface and reads PathLike content asynchronously.

Handling errors

Connection failures raise an x_twitter_scraper.APIConnectionError subclass. Non-2xx responses raise an APIStatusError subclass with status_code and response. Every SDK error inherits from x_twitter_scraper.APIError.

import x_twitter_scraper
from x_twitter_scraper import XTwitterScraper

client = XTwitterScraper()

try:
    client.x.tweets.search(
        q="from:elonmusk",
        limit=10,
    )
except x_twitter_scraper.APIConnectionError as e:
    print("Could not reach the server. Check the connection.")
    print(e.__cause__)  # Underlying httpx exception.
except x_twitter_scraper.RateLimitError as e:
    print("Rate limited. Retry later.")
except x_twitter_scraper.APIStatusError as e:
    print("Server returned a non-2xx status.")
    print(e.status_code)
    print(e.response)

The SDK uses these error classes.

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 max_retries to change or disable retries. Set it on the client, or on 1 request through with_options.

from x_twitter_scraper import XTwitterScraper

client = XTwitterScraper(
    max_retries=0,
)

client.with_options(max_retries=5).x.tweets.search(
    q="from:elonmusk",
    limit=10,
)

Timeouts

Requests time out after 1 minute. Set a float or httpx.Timeout through timeout. Set it on the client, or on 1 request through with_options.

from x_twitter_scraper import XTwitterScraper

client = XTwitterScraper(
    timeout=20.0,
)

client = XTwitterScraper(
    timeout=httpx.Timeout(60.0, read=5.0, write=10.0, connect=2.0),
)

client.with_options(timeout=5.0).x.tweets.search(
    q="from:elonmusk",
    limit=10,
)

Timeouts raise APITimeoutError.

Timed-out requests follow the default retry policy.

Advanced

Logging

The SDK uses Python's logging module. Set X_TWITTER_SCRAPER_LOG to info to enable logs.

$ export X_TWITTER_SCRAPER_LOG=info

Use debug for request and response details.

Distinguishing None, null & missing fields

Both missing and explicit null response fields map to None. Check .model_fields_set to distinguish them.

if response.my_field is None:
    if "my_field" not in response.model_fields_set:
        print('The response omitted "my_field".')
    else:
        print('The response set "my_field" to null.')

Accessing raw response data

Prefix a method with .with_raw_response. to access the raw response.

from x_twitter_scraper import XTwitterScraper

client = XTwitterScraper()
response = client.x.tweets.with_raw_response.search(
    q="from:elonmusk",
    limit=10,
)
print(response.headers.get("X-My-Header"))

tweet = response.parse()  # Parse the regular x.tweets.search() result.
print(tweet.has_next_page)

Sync methods return APIResponse. Async methods return AsyncAPIResponse with awaitable content readers.

.with_streaming_response

The raw-response interface reads the complete body immediately. Use .with_streaming_response and a context manager to read it on demand. Call .read(), .text(), .json(), an iterator, or .parse(). The async client provides async versions of these methods.

with client.x.tweets.with_streaming_response.search(
    q="from:elonmusk",
    limit=10,
) as response:
    print(response.headers.get("X-My-Header"))

    for line in response.iter_lines():
        print(line)

The context manager always closes the response.

Making custom or undocumented 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.

import httpx

response = client.post(
    "/foo",
    cast_to=httpx.Response,
    body={"my_param": True},
)

print(response.headers.get("x-foo"))

Undocumented request parameters

Pass extra values through extra_query, extra_body, or extra_headers.

Undocumented response properties

Read an extra field through response.unknown_prop. Use response.model_extra to get every extra field as a dictionary.

Configuring the HTTP client

Replace the httpx client to configure these options.

import httpx
from x_twitter_scraper import XTwitterScraper, DefaultHttpxClient

client = XTwitterScraper(
    # Or use the `X_TWITTER_SCRAPER_BASE_URL` env var
    base_url="http://my.test.server.example.com:8083",
    http_client=DefaultHttpxClient(
        proxy="http://my.test.proxy.example.com",
        transport=httpx.HTTPTransport(local_address="0.0.0.0"),
    ),
)

Use with_options() to replace it for one request.

client.with_options(http_client=DefaultHttpxClient(...))

Managing HTTP resources

Garbage collection closes the client's HTTP connections. Call .close() or use a context manager to close them earlier.

from x_twitter_scraper import XTwitterScraper

with XTwitterScraper() as client:
    # Make requests here.
    ...

# The HTTP client is closed.

Versioning

This package follows SemVer with these exceptions.

  1. Static type changes that preserve runtime behavior.
  2. Changes to undocumented internals that remain technically public.
  3. Changes unlikely to affect normal use.

Open an issue with questions, bugs, or suggestions.

Determining the installed version

If new features are missing, Python may still load an older package. Check the runtime version.

import x_twitter_scraper

print(x_twitter_scraper.__version__)

Requirements

The SDK requires Python 3.10 or later.

More Xquik tools

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.

Metadata

Release files for x_twitter_scraper 0.14.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for x_twitter_scraper 0.14.0
File Size Uploaded
x_twitter_scraper-0.14.0.tar.gz 437.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for x_twitter_scraper 0.14.0
File Interpreter ABI Platform
x_twitter_scraper-0.14.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.1 MB

Release files / x_twitter_scraper-0.14.0.tar.gz

Download URL x_twitter_scraper-0.14.0.tar.gz
Size 437.1 kB
Tags Source
SHA-256 checksum
How to use checksums
75de88e16b9dab0315c60695c2b0c2c195e136950c0477343ce46c14984302e4
BLAKE2b-256 checksum
How to use checksums
15cb784484ae0cb3a73fd6f0d5586eb0b4165a2a90679e1473313fba0fb3c30e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / x_twitter_scraper-0.14.0-py3-none-any.whl

Download URL x_twitter_scraper-0.14.0-py3-none-any.whl
Size 644.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
11d2fc457e03d5096efc9df0d58890492879d1854cc0a4291f49e191aca91505
BLAKE2b-256 checksum
How to use checksums
1badb16f52ff0015ce0e41388e7c6b3c27218c2ccbdfeb6d70c5841d977de1dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release history Release notifications | RSS feed

0.16.0

2 release files

0.15.0

2 release files

This release

0.14.0 This release

2 release files

0.13.1

2 release files

0.13.0

2 release files

0.11.2

2 release files

0.11.1

2 release files

0.11.0

2 release files

0.10.1

2 release files

0.10.0

2 release files

0.8.1

2 release files

0.8.0

2 release files

0.7.0

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.2

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.1

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page