Twitter API for Academic Research in 2026: Costs and Options
Free academic access to the Twitter API ended in 2023. See what researchers can use now, what 100,000 tweets cost, and how to collect them with Python.
Twitter's free access for academics ended in 2023. If you study Twitter today, you have three realistic choices: pay X directly, apply for research access through the EU if your project qualifies, or use a third-party API like TweetAPI.
For most studies, the deciding factor is the budget. Collecting 100,000 tweets from a keyword search costs $500 on X's own API. With TweetAPI it takes about 5,000 requests, which is roughly $2.50 out of a $5 prepaid pack. You don't need an X developer account, and there's no subscription. If you're a researcher, you can also ask us for 10,000 free units to run a proper pilot.
This guide walks through what each option costs, how to collect the data with Python, and what to write down so your dataset holds up when you publish.
Prices checked: October 29, 2026.
Disclosure: TweetAPI wrote this guide. TweetAPI is a third-party service and isn't affiliated with X Corp.
What Happened to Free Academic Access
From 2021, Twitter's Academic Research track gave approved researchers free access to the full tweet archive, up to 10 million tweets a month. In February 2023, Twitter announced the end of free API access, and by the middle of that year the academic keys had stopped working.
There's no academic plan today. Researchers pay the same prices as everyone else.
Your Options Today
X's Own API
X now charges per item you read: $0.005 for each tweet and $0.010 for each user profile or follower. You buy credits in advance, and there's no subscription. The self-serve plan stops at 3 million tweet reads a month. Our Twitter API pricing guide has the full list of rates.
This is the right choice when your ethics board or funder requires data straight from X, or when you need X's own full-archive search. It's also the most expensive route by far.
EU Research Access
The EU's Digital Services Act lets approved researchers ask large platforms for data. With X, it only covers research into "systemic risks" in the EU, such as the spread of illegal content or threats to elections, along with research on how well X handles those risks.
You apply through the European Commission's data access portal, not through X. You need to be affiliated with a university or research organization, show how you'll protect the data, and explain why you can't do the study with data from other sources. X has a help page on the process. Expect it to take a while, and it doesn't help if your topic falls outside the EU rules.
A Third-Party API
A third-party API gives you its own API key, so you can request public Twitter data without dealing with X's developer portal. You sign up, create a key, and start sending requests. TweetAPI is one of these services, and our comparison of Twitter API alternatives covers others.
The main difference is cost. The tradeoff is that your data comes through a company other than X, so describe your collection method clearly in your paper. The sections below show what to record.
What Common Research Jobs Cost
| Research job | TweetAPI requests | TweetAPI cost | X API cost |
|---|---|---|---|
| 100,000 tweets from a keyword search | About 5,000 (20 tweets each) | About $2.50 | $500 |
| 1 million tweets from a list of tweet IDs | 5,000 (200 IDs each) | About $2.50 | $5,000 |
| 100,000 follower profiles | 500 (200 profiles each) | About $0.25 | $1,000 |
Each time your code asks for a page of data, that's one request. TweetAPI measures usage in units, and most requests use one unit, no matter how many tweets come back. Pay-as-you-go units cost $5 for 10,000, so the first two jobs together fit in a single $5 pack.
A few things change the real number. A search page can return fewer than 20 tweets, and a request that comes back empty still uses a unit. You aren't charged for requests that fail because of a server error or because you sent too many requests in a minute, so retrying them costs nothing extra.
How Long a Collection Takes
Pay as you go allows 60 requests a minute. At 20 tweets a page, that's up to about 1,200 tweets a minute from search, so 100,000 tweets take about an hour and a half at full speed. The simple examples below pause between requests, so expect them to take a bit longer.
Monthly plans allow between 60 and 500 requests a minute and come with a bigger allowance. They suit regular collection, but they can also be the cheaper choice for one large study: the Pro plan gives you 100,000 units for $17, while the same number of units costs $50 on pay as you go. Plan units don't carry over to the next month, so cancel once you're done. For a smaller study, a prepaid pack is usually enough, and its units stay valid for 365 days.
Collecting the Data With Python
The examples below use Python. Install the requests library first with pip install requests. The same requests work from R or any other language that can call a web API.
First, create a free account and an API key. The key works like a password: your code sends it with every request so TweetAPI knows which account is asking. New accounts get 100 free units without a credit card, which is enough to test your queries before you pay.
Then open a terminal and save the key as an environment variable. That way your code can read the key without it being written into your script:
export TWEETAPI_KEY="your_api_key_here"
On Windows PowerShell, use $env:TWEETAPI_KEY = "your_api_key_here" instead. Run your Python script from the same terminal window.
Put this block at the top of your Python script. Each example below uses it. It sends a request, waits between calls so you stay under 60 a minute, and retries if a request fails for a temporary reason:
import json
import os
import time
import requests
API = "https://api.tweetapi.com/tw-v2"
HEADERS = {"X-API-Key": os.environ["TWEETAPI_KEY"]}
def get(path, params):
for attempt in range(5):
response = requests.get(API + path, headers=HEADERS, params=params, timeout=60)
if response.status_code == 429 or response.status_code >= 500:
time.sleep(5 * 2**attempt)
continue
response.raise_for_status()
time.sleep(1)
return response.json()
response.raise_for_status()
The free trial allows 10 requests a minute, so while you're testing on it, change time.sleep(1) to time.sleep(6).
Collect Tweets by Keyword and Date
Search follows the same rules as the search box on X. You can combine words, exact phrases, accounts and languages, and limit results to a time window. The advanced search builder helps you put a query together.
For the time window, use since_time: and until_time:. They take a Unix timestamp, which is a date and time written as a single number. The code below works out that number for you from a date in UTC, the world's reference time. The shorter since: and until: filters take a plain date, but in our tests they followed US Pacific time, and until: included the day you named. A query for September also returned tweets from October 1.
Results come in pages of about 20 tweets. Each page includes a cursor, which you send back to get the next page:
def search(query, max_pages=500):
cursor = None
for _ in range(max_pages):
params = {"query": query, "type": "Latest"}
if cursor:
params["cursor"] = cursor
body = get("/search", params)
tweets = body.get("data") or []
yield from tweets
cursor = (body.get("pagination") or {}).get("nextCursor")
if not tweets or not cursor:
break
Then pick your dates and collect:
from datetime import datetime, timezone
start = datetime(2026, 9, 1, tzinfo=timezone.utc)
end = datetime(2026, 10, 1, tzinfo=timezone.utc)
query = (
f'"climate change" lang:en '
f"since_time:{int(start.timestamp())} until_time:{int(end.timestamp())}"
)
with open("tweets.jsonl", "w", encoding="utf-8") as file:
for tweet in search(query):
file.write(json.dumps(tweet, ensure_ascii=False) + "\n")
Each line in tweets.jsonl is one tweet with its text, author, date and engagement counts. max_pages puts a ceiling on how many units one run can use.
Before you analyze the data, check each tweet's createdAt field, which holds the date and time it was posted. This drops anything that slipped in from outside your window:
def in_range(tweet):
created = datetime.strptime(tweet["createdAt"], "%Y-%m-%dT%H:%M:%S.%fZ")
return start <= created.replace(tzinfo=timezone.utc) < end
with open("tweets.jsonl", encoding="utf-8") as file:
tweets = [json.loads(line) for line in file]
kept = [tweet for tweet in tweets if in_range(tweet)]
print(f"Kept {len(kept)} of {len(tweets)} tweets")
Turn a List of Tweet IDs Back Into Tweets
Many published datasets share only tweet IDs, because X's rules limit sharing full tweets. Getting the tweets back from the IDs is often called "rehydrating" a dataset. The tweet lookup takes up to 200 IDs per request:
with open("tweet_ids.txt", encoding="utf-8") as file:
ids = [line.strip() for line in file if line.strip()]
found = 0
with open("hydrated.jsonl", "w", encoding="utf-8") as file:
for i in range(0, len(ids), 200):
batch = ids[i : i + 200]
body = get("/tweet/details-by-ids", {"ids": ",".join(batch)})
tweets = (body.get("data") or {}).get("tweets") or []
found += len(tweets)
for tweet in tweets:
file.write(json.dumps(tweet, ensure_ascii=False) + "\n")
print(f"{found} of {len(ids)} tweets are still available")
Some tweets won't come back. They may have been deleted, or the account may have gone private or been suspended. That's normal for older datasets, so report how many you recovered.
Collect an Account's Followers
To study a follower network, first look up the account's numeric ID, then page through its followers 200 at a time:
user = get("/user/by-username", {"username": "NASA"})["data"]
cursor = None
with open("followers.jsonl", "w", encoding="utf-8") as file:
for _ in range(50):
params = {"userId": user["id"], "count": "200"}
if cursor:
params["cursor"] = cursor
body = get("/user/followers-list", params)
followers = body.get("data") or []
for follower in followers:
file.write(json.dumps(follower, ensure_ascii=False) + "\n")
cursor = (body.get("pagination") or {}).get("nextCursor")
if not followers or not cursor:
break
This loop stops after 50 pages, about 10,000 followers. Raise the limit when you're ready to collect more.
Other Data You Can Collect
The same pattern works for an account's own tweets, the replies in a conversation, tweets from the members of a list, posts in a community and details about Spaces. The API documentation lists every request.
Making Your Dataset Hold Up
Reviewers will ask how you got your data. These habits make that question easy to answer:
- Write down every query exactly as you ran it, with the date and time of collection.
- Run a pilot first. Use your free units to collect a small sample, then check that it looks like what you expected.
- Don't assume search returns everything. Search results come from X's search, which doesn't promise every matching tweet. If your study depends on complete counts, explain in your limitations section that search may miss some matching tweets.
- Check older periods before you rely on them. Search can reach back to Twitter's first year: in a test on October 29, 2026, a search for tweets from March 2006 returned results. Still, test your own date range before you plan the study around it.
- Note when you collected engagement numbers. Likes, reposts and view counts keep changing after a tweet is posted.
Your methods section can then describe the collection in a few sentences. For example, with your own numbers in the brackets:
We collected English-language tweets containing "climate change" posted between September 1 and September 30, 2026 (UTC), using the search feature of TweetAPI (tweetapi.com), a third-party API for public Twitter data. The data was collected on [date]. Of [number] tweets returned, [number] fell inside the date range and were kept for analysis.
Ethics, Terms and Sharing Your Data
Using a third-party API doesn't change your responsibilities as a researcher. Get approval from your ethics board when your project needs it. Collect only the fields you need, and be careful about drawing conclusions about individual people's sensitive traits.
Before you share a dataset, check X's Developer Policy, the TweetAPI terms and the rules of the journal or archive you're publishing in. Many researchers share tweet IDs instead of full tweets for this reason.
Free Pilot Units for Researchers
The 100 free units every new account gets are enough to try the API, but not to test a real study. If you're a researcher, email support@tweetapi.com from your university address with a line or two about your project, and we'll add 10,000 free units to your account. That's enough for about 200,000 tweets from search.
It's one pilot per person, and we read each request ourselves.
Paying From a Grant or University Budget
Prepaid packs are one-time purchases, starting at $5 for 10,000 units. Nothing renews, and the units last 365 days, so you can pay once and use the units over the year. You can pay by card or with crypto.
If your university needs an invoice, email support@tweetapi.com and we'll issue a proper one for your purchase.
FAQ
Is there still free Twitter API access for academics?
No. The free Academic Research track ended in 2023. Your options now are X's pay-per-use API, EU research access if your project qualifies, or a third-party API.
Do you offer anything for researchers?
Yes. Email support@tweetapi.com from your university address with a short description of your project, and we'll add 10,000 free pilot units to your account. It's one pilot per person.
How far back can I search?
In our tests, search reached tweets from 2006. X doesn't promise complete results for any period, though, so run a small pilot on your own date range first.
Do I need an X developer account?
Not with TweetAPI. You need a TweetAPI account and API key. You only need an X developer account if you use X's own API.
Can I use TweetAPI data in a thesis or a paper?
Many researchers use third-party data sources. Check with your supervisor and ethics board, follow the terms above, and describe how you collected the data in your methods section.
How many tweets can I collect in a day?
On pay as you go, search can return up to about 1,200 tweets a minute. At that rate a full day comes to well over a million tweets, as long as you have the units for it.
Get Started
Create a free account and run your first queries with the 100 free units. If you're a researcher, ask for pilot units once your account is set up. When you're ready to collect at scale, buy a prepaid pack on the pricing page. If you're comparing providers first, start with our Twitter API alternatives guide.