Back to Blog
tutorialpythonnode.jstwitter apisdk

Twitter API with Python & TypeScript: Complete SDK Guide

Call a Twitter API from Python or TypeScript with working SDK examples for profiles, search, pagination, retries, errors, and production setup.

TweetAPI
9 min read

Use the TweetAPI Python or TypeScript SDK to fetch a public profile, search posts, and paginate results. These clients use a TweetAPI key, not an official X API token. If you need official X access, compare the API and client options first.

Start with Python or TypeScript, then search posts and paginate followers.

Checked October 12, 2026 with the Python and Node.js SDKs 2.5.0 and simulated API responses.

Disclaimer: TweetAPI is a third-party service. Not affiliated with X Corp.

Python Quickstart

This example fetches one public profile and prints its ID, username, and follower count. Use Python 3.11 or newer from the supported-version list.

Create a TweetAPI account, then create an API key in the dashboard. The trial provides 100 one-time requests without a credit card. You do not need an X developer app for this public-data request.

Create an isolated environment. On macOS or Linux:

python3 -m venv .venv
source .venv/bin/activate
python -m pip install tweetapi==2.5.0

On Windows PowerShell, use these commands instead:

py -3 -m venv .venv
.\.venv\Scripts\python.exe -m pip install tweetapi==2.5.0

The version pin makes this example reproducible. Review later package releases before upgrading an existing application.

Save this as first_profile.py:

import argparse
import getpass
import json
import os

from tweetapi import NetworkError, TweetAPI, TweetAPIError

parser = argparse.ArgumentParser(description="Fetch one public Twitter profile.")
parser.add_argument("username", help="An existing public username, without @")
args = parser.parse_args()
username = args.username.removeprefix("@").strip()
if not username:
    parser.error("Provide a non-empty username.")

api_key = os.environ.get("TWEETAPI_KEY") or getpass.getpass("TweetAPI key: ")
if not api_key.strip():
    raise SystemExit("Provide a TweetAPI key.")

client = TweetAPI(api_key=api_key.strip(), max_retries=0)
try:
    response = client.user.get_by_username(username=username)
except NetworkError:
    raise SystemExit("Request failed: NetworkError. Check connectivity before retrying.") from None
except TweetAPIError as error:
    raise SystemExit(
        f"Request failed: {type(error).__name__} (status {error.status_code}). "
        "See the troubleshooting table below."
    ) from None

user = response["data"]
print(json.dumps({
    "id": user["id"],
    "username": user["username"],
    "followerCount": user["followerCount"],
}, indent=2))

Replace YOUR_USERNAME with an existing public account and run:

python first_profile.py YOUR_USERNAME

On Windows PowerShell:

.\.venv\Scripts\python.exe first_profile.py YOUR_USERNAME

Enter your TweetAPI key at the hidden prompt. If TWEETAPI_KEY is already set in the process environment, the script uses it instead. The prompt does not save the key or set an environment variable for other programs.

A successful response prints this shape. These values are synthetic, not a live account result:

{
  "id": "1234567890123456789",
  "username": "example_user",
  "followerCount": 1234
}

The profile fields come from response["data"]. IDs stay strings, and response fields retain camelCase. The SDK's get_by_username method calls GET /tw-v2/user/by-username with your key in X-API-Key.

This first-run example disables automatic retries, so it makes one SDK request attempt. The SDK normally allows three retries after the initial attempt. Once the first call works, configure retries and request limits for your application using the retry section.

If the first request fails

ResultNext step
ModuleNotFoundError: tweetapiInstall the package with the same Python executable used to run the file.
Empty keyEnter the key from your TweetAPI dashboard. An X developer token is a different credential.
ValidationError, status 400Check the username and the endpoint's required parameters.
AuthenticationError, status 401Check that the TweetAPI key is valid and active.
ForbiddenError, status 403Check the account's access and the endpoint requirements.
NotFoundError, status 404Check the username and whether the account remains accessible.
RateLimitError, status 429Check error.code. RATE_LIMITED clears after error.retry_after seconds; QUOTA_EXHAUSTED or SUBSCRIPTION_INACTIVE needs a plan or balance change in the dashboard. Repeated immediate retries do not fix any of them.
NetworkError or ServerErrorCheck connectivity or service status before retrying.

Add later Python snippets to this file after the client is created so they can reuse client. When creating another client in the retry example, reuse the api_key variable from this quickstart.

For search examples later in this guide, a successful empty data array means no results were returned. That is different from a failed profile request.

TypeScript Quickstart

Use Node.js 22 or 24 LTS. In a new directory, install the SDK and a local TypeScript runner:

npm init -y
npm install tweetapi-node@2.5.0
npm install --save-dev tsx@4.23.1

Create .env with your TweetAPI key, and add .env to .gitignore:

TWEETAPI_KEY=your_api_key_here

Save this as first_profile.mts. The .mts extension tells the runner this is an ES module:

import { TweetAPI } from "tweetapi-node";

const apiKey = process.env.TWEETAPI_KEY?.trim();
const username = process.argv[2]?.trim().replace(/^@/, "");
if (!apiKey || !username) {
  throw new Error("Set TWEETAPI_KEY and supply an existing public username.");
}

const client = new TweetAPI({ apiKey, retry: false });
const response = await client.user.getByUsername({ username });
console.log(JSON.stringify({
  id: response.data.id,
  username: response.data.username,
  followerCount: response.data.followerCount,
}, null, 2));

Replace YOUR_USERNAME with an existing public account and run:

npx tsx --env-file=.env first_profile.mts YOUR_USERNAME

The output has the same profile shape as the Python example above. This first call disables retries; configure retries after verifying the key and response. Keep API keys on the server, never in a browser bundle. The Python key prompt does not set an environment variable for this process.

Run later TypeScript examples in this file after creating client. Initialize one client per process and reuse it. Python methods and arguments use snake_case, Node.js methods use camelCase, and returned fields remain camelCase under data.

Search Posts

The search endpoint requires a query and a title-case result type.

Python

results = client.explore.search(
    query='"climate data" lang:en',
    type="Latest",
)

for post in results["data"]:
    print(f"@{post['author']['username']}: {post['text'][:100]}")

Node.js / TypeScript

const results = await client.explore.search({
  query: '"climate data" lang:en',
  type: "Latest",
});

for (const post of results.data) {
  if ("text" in post) {
    console.log(`@${post.author.username}: ${post.text.slice(0, 100)}`);
  }
}

Valid result types are Latest, Top, People, Photos, and Videos. Search operators are passed in the query string.

To run searches on a schedule and track newly found posts, see the Python brand monitor.

Paginate Followers

The followers endpoint returns data and pagination.nextCursor. The SDK helpers can yield individual items across pages.

Python

from tweetapi import paginate

for user in paginate(
    lambda cursor: client.user.get_followers(
        user_id="10017528",
        cursor=cursor,
    ),
    max_pages=5,
):
    print(f"@{user['username']}: {user['followerCount']} followers")

Node.js / TypeScript

import { paginate } from "tweetapi-node";

for await (const user of paginate(
  (cursor) => client.user.getFollowers({
    userId: "10017528",
    cursor,
  }),
  { maxPages: 5 }
)) {
  console.log(`@${user.username}: ${user.followerCount} followers`);
}

Always set an appropriate max_pages or maxPages when the application does not need an entire collection.

Iterate Full Pages

Use paginate_pages in Python or paginatePages in Node.js when you need page-level metadata.

Python

from tweetapi import paginate_pages

for page in paginate_pages(
    lambda cursor: client.explore.search(
        query="tweetapi",
        type="Latest",
        cursor=cursor,
    ),
    max_pages=3,
):
    print(len(page["data"]))
    print(page["pagination"].get("nextCursor"))

Node.js / TypeScript

import { paginatePages } from "tweetapi-node";

for await (const page of paginatePages(
  (cursor) => client.explore.search({
    query: "tweetapi",
    type: "Latest",
    cursor,
  }),
  { maxPages: 3 }
)) {
  console.log(page.data.length);
  console.log(page.pagination.nextCursor);
}

Handle Typed Errors

The SDKs normalize API errors into specific exception classes.

Python

from tweetapi import (
    AuthenticationError,
    ErrorCode,
    ForbiddenError,
    NetworkError,
    NotFoundError,
    RateLimitError,
    ServerError,
    TweetAPIError,
    ValidationError,
)

try:
    user = client.user.get_by_username(username="missing-account-example")
except RateLimitError as error:
    if error.code == ErrorCode.RATE_LIMITED:
        print(f"Retry in about {error.retry_after} seconds")
    else:
        print(f"Check usage and billing: {error.code}")
except NotFoundError:
    print("User not found")
except AuthenticationError:
    print("Check the TweetAPI key")
except ForbiddenError:
    print("The credential cannot perform this operation")
except ValidationError as error:
    print(f"Invalid request: {error.message}")
except NetworkError:
    print("No API response was received")
except ServerError:
    print("TweetAPI returned a server error")
except TweetAPIError as error:
    print(error.code, error.status_code, error.message)

Node.js / TypeScript

import {
  AuthenticationError,
  ConnectionError,
  ErrorCode,
  ForbiddenError,
  NotFoundError,
  RateLimitError,
  ServerError,
  TweetAPIError,
  ValidationError,
} from "tweetapi-node";

try {
  await client.user.getByUsername({ username: "missing-account-example" });
} catch (error) {
  if (error instanceof RateLimitError) {
    if (error.code === ErrorCode.RATE_LIMITED) {
      console.log(`Retry in about ${error.retryAfter} seconds`);
    } else {
      console.log(`Check usage and billing: ${error.code}`);
    }
  } else if (error instanceof NotFoundError) {
    console.log("User not found");
  } else if (error instanceof AuthenticationError) {
    console.log("Check the TweetAPI key");
  } else if (error instanceof ForbiddenError) {
    console.log("The credential cannot perform this operation");
  } else if (error instanceof ValidationError) {
    console.log(`Invalid request: ${error.message}`);
  } else if (error instanceof ConnectionError) {
    console.log("No API response was received");
  } else if (error instanceof ServerError) {
    console.log("TweetAPI returned a server error");
  } else if (error instanceof TweetAPIError) {
    console.log(error.code, error.statusCode, error.message);
  }
}

The Python SDK exports NetworkError; the Node.js SDK exports ConnectionError. Both also expose TweetAPIError, AuthenticationError, ForbiddenError, ValidationError, NotFoundError, RateLimitError, and ServerError.

error.code carries the API's reason when it sends one, such as RATE_LIMITED, QUOTA_EXHAUSTED, ACCOUNT_SUSPENDED, or PROXY_ERROR. Both SDKs list the known values in ErrorCode. Errors without a reason use UNKNOWN_ERROR.

Configure Automatic Retry

Both SDKs retry read requests after transient 429, 5xx, timeout, and connection failures. Client errors such as 400, 401, 403, and 404 are not retried.

Requests that change something, such as posting, liking, following, sending a DM, or logging in, are retried only when the API answers 429 or 503 with a Retry-After header, which means the request was not processed. Any other failure is returned to your code, so an action is never performed twice; check whether it completed before you repeat it. A failed proxy (PROXY_ERROR, PROXY_TIMEOUT) or a used-up or inactive plan (QUOTA_EXHAUSTED, SUBSCRIPTION_INACTIVE) is never retried.

The default max_retries or maxRetries value is 3. That means one initial request plus up to three retries, for at most four attempts.

Python

client = TweetAPI(
    api_key=api_key,
    max_retries=5,
    initial_retry_delay=2.0,
    backoff_multiplier=2.0,
    max_retry_delay=30.0,
)

Node.js / TypeScript

const client = new TweetAPI({
  apiKey: process.env.TWEETAPI_KEY!,
  retry: {
    maxRetries: 5,
    initialRetryDelay: 2_000,
    backoffMultiplier: 2,
    maxRetryDelay: 30_000,
  },
});

The clients wait for the API's Retry-After value when it is present and otherwise use bounded backoff. Automatic retry does not replace a shared concurrency queue or request budget.

TweetAPI SDK Endpoint Coverage

Both SDKs group methods by API resource:

ResourcePython exampleNode.js example
Usersclient.user.get_by_username(...)client.user.getByUsername(...)
Postsclient.tweet.get_details_and_conversation(...)client.tweet.getDetailsAndConversation(...)
Searchclient.explore.search(...)client.explore.search(...)
Create postsclient.post.create_post(...)client.post.createPost(...)
Engagementclient.interaction.favorite_post(...)client.interaction.favoritePost(...)
Listsclient.list.get_details(...)client.list.getDetails(...)
Communitiesclient.community.get_tweets(...)client.community.getTweets(...)
Spacesclient.space.get_by_id(...)client.space.getById(...)
Encrypted DMsclient.xchat.send(...)client.xchat.send(...)
DMsclient.dm.get_conversation(...)client.dm.getConversation(...)

See the package READMEs for the complete method list:

Account-Authorized Operations

Posting, engagement, profile, DM, and related account operations require an authToken plus the fields documented for that endpoint. Some media or account workflows require additional parameters such as a proxy or media object.

Do not assume authToken is the only extra field. Start from the exact endpoint page, such as favorite post, and protect account tokens as sensitive credentials.

Choose the API and Client First

An SDK only simplifies the API behind it; it does not make different APIs interchangeable.

OptionConnects toBest fitImportant boundary
Official Python XDKOfficial X APITeams that need official X developer access and first-party API capabilitiesRequires official X API credentials and uses the official API's products, limits, and pricing
TweepyOfficial X APIExisting Python projects built around Tweepy's official API wrappersCommunity library; still requires official API access
TweetAPI Python or TypeScript SDKTweetAPIPublic-data, research, monitoring, and documented account-authorized workflows using TweetAPIThird-party service with separate credentials, endpoints, and terms
Raw HTTPWhichever API URL you callUnsupported languages or applications that need full transport controlYou own URLs, headers, types, pagination, retry, and error mapping

For provider pricing and access requirements, see the Twitter API alternatives guide.

Install the TweetAPI SDKs

The Python quickstart installs tweetapi==2.5.0 in a virtual environment. The TypeScript quickstart installs tweetapi-node@2.5.0 and a local TypeScript runner. Use those commands in a new project; review release changes before upgrading an existing one.

The packages list Python 3.9 and Node.js 18 as their minimum supported versions. For production, choose a supported Python version and Node.js 22 or 24 LTS from the Node.js release schedule.

SDK vs Raw HTTP

The SDKs call the same /tw-v2 endpoints as raw HTTP, with the same response shapes and X-API-Key authentication. Their methods handle URL construction and the following tasks:

ConcernRaw HTTPSDK
Request URLs and headersYour codeClient handles them
Response typesDefine your ownIncluded
PaginationCursor loopIterator helpers
Error mappingCheck status/bodyTyped errors
Transient retryImplement and testBuilt in and configurable
Runtime dependencyNative client onlyrequests for Python; none for Node.js
Custom transport controlMaximumLess direct

Use raw HTTP when you want full control or work in an unsupported language. Use an SDK when consistent retries, types, and pagination reduce application code. The raw Node.js tutorial shows the non-SDK approach.

FAQ

Do I need an SDK to use TweetAPI?

No. See the SDK and raw HTTP comparison.

Are the SDKs open source?

Yes. Both repositories use the MIT License and accept issue reports through GitHub.

Do the SDKs change the API response fields?

No. Both SDKs retain the API's camelCase response fields.

Does automatic retry prevent rate limits?

No. It handles a transient failure after it happens. You still need to control concurrency and choose a plan that fits peak request volume.

Can I disable retries?

Yes. Use max_retries=0 in Python or retry: false in Node.js.

Where should I report a problem?

Open an issue in the relevant GitHub repository for SDK behavior. For API response or endpoint issues, contact support@tweetapi.com or use TweetAPI on Telegram.

Try a follower export

Once your profile and pagination requests work, use the Python follower exporter to save two pages to CSV and resume from a checkpoint.