twitterapi.io is an independent third-party service. Not affiliated with X Corp.

Blogtweetstats

TweetStats Alternative: How to Graph Your Tweet Stats Now That TweetStats Is Gone

By Sarah Wong•6 min read
Timeline of TweetStats from its first captures in January 2008, through 100,000 and nearly 1,000,000 users, a December 2022 relaunch, to its February 2023 shutdown and today's memorial page
TweetStats' 15-year run, reconstructed from Internet Archive captures of tweetstats.com and the live memorial page.

If you used Twitter between 2008 and 2022, there's a fair chance you typed your username into TweetStats at least once to see your tweets per hour or your TweetCloud. Its homepage said it was "in use by over 100,000 Twitter-folk" in 2012 and "nearly 1,000,000 Twitter-folk" by January 2020, per Internet Archive captures. Searching for it today lands you on a memorial page.

This page covers what happened to TweetStats, using the live site and archived captures rather than guesses; lists exactly what it charted; maps each chart to a working replacement; and gives a runnable Python script that rebuilds the full TweetStats graph set for any public account. If you want the raw metric fields rather than the graphs, the Twitter stats API guide linked below goes into likes, views and impressions in more detail.

01 — Section

What happened to TweetStats

We checked the live domain and pulled the Internet Archive's capture index (the Wayback Machine CDX API) for tweetstats.com, then opened captures from each period.

PeriodWhat tweetstats.com showed
January 2008First captures: the original TweetStats graphing tool
2012"In use by over 100,000 Twitter-folk", plus a warning that Twitter's pagination limits made its future "somewhat uncertain"
January 2020Same tool, "in use by nearly 1,000,000 Twitter-folk"; stats refreshed if you returned after 8 hours
December 2022Relaunched as "Graph your Tweets! Build Charts, Download CSVs" with a Slack integration: keyword queries over the past 30 days, free for the last 7 days or $1 per query
2025-2026 (live)Memorial page: "In memory of TweetStats, January 2008 - February 2023"

On the memorial page, Damon Cortesi writes that the first version "simply scraped the website" because the Twitter API didn't exist yet, and that he shut the site down when free API access ended: "Access to the data is no longer free, and I have no desire to keep this site running." That's the creator's own account, so there's no ambiguity about whether it's coming back. The bare tweetstats.com hostname returned a 502 error when we checked; www.tweetstats.com serves the memorial.

02 — Section

Every TweetStats graph and what replaces it

An archived TweetStats results page (captured August 2014) lists the full set of views it produced for an account. All of them can be rebuilt from fields on each tweet.

TweetStats viewWhat it showedField to rebuild it
Tweet timelineTweets per month, zoomable to a single monthcreatedAt
Tweets per dayTweets by weekdaycreatedAt
Tweets per hourTweets by hour of daycreatedAt
Tweet densityWeekday × hour heatmapcreatedAt
Tweet @'sAccounts you replied to mostisReply, inReplyToUsername
Interface usedWhich app each tweet was sent fromsource
Retweets ofAccounts you retweeted mostretweeted_tweet.author.userName
TweetCloudMost-used wordstext
HashCloudMost-used hashtagsentities.hashtags

Field names come from the TwitterAPI.io OpenAPI spec. One TweetStats view is weaker than it used to be: "interface used" depends on X still exposing a meaningful source value for the tweet, so expect more generic labels on recent tweets than you'd have seen in 2014.

03 — Section

Free options, and where they fall short

X's built-in analytics. If you only care about your own account, start here. It shows impressions and engagement that no outside tool can see, such as profile visits and link clicks. It isn't built around TweetStats' view of posting habits (when you tweet, who you reply to, which words you lean on), and it can't show anyone else's account.

Your X data archive. X lets you download an archive of your own account from settings. It contains every tweet with a timestamp, so you can build TweetStats-style charts from it in a spreadsheet. It's complete and free, but it's your account only and you have to request a fresh archive each time.

X advanced search. Searching from:username since:2026-01-01 until:2026-02-01 on x.com shows an account's tweets for a month, which is enough to eyeball activity but gives you no counts or charts.

For graphs of any public account, refreshed whenever you want, you need the tweets as data. That's what the API route below provides.

04 — Section

Rebuild the core graphs with the API

TwitterAPI.io's advanced_search takes X's search syntax. Per its docs, date bounds go in as unix timestamps with since_time: and until_time:; results come back newest-first in pages with has_next_page and next_cursor. The snippet below pulls six months of an account's tweets and prints the two charts people remember most from TweetStats: tweets per month and tweets per hour.

createdAt is in UTC (for example Tue Dec 10 07:00:30 +0000 2024). Convert it to the account's local timezone before reading anything into the per-hour chart.

python
# The two core TweetStats graphs: tweets per month and per hour (UTC)
import os, requests
from collections import Counter
from datetime import datetime, timezone

HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
lo = int(datetime(2026, 1, 1, tzinfo=timezone.utc).timestamp())
hi = int(datetime(2026, 7, 1, tzinfo=timezone.utc).timestamp())
query = f"from:nasa since_time:{lo} until_time:{hi}"

cursor, tweets = "", []
while True:
    r = requests.get(
        "https://api.twitterapi.io/twitter/tweet/advanced_search",
        headers=HEADERS,
        params={"query": query, "queryType": "Latest", "cursor": cursor},
        timeout=20,
    )
    r.raise_for_status()
    body = r.json()
    tweets += body.get("tweets", [])
    if not body.get("has_next_page"):
        break
    cursor = body["next_cursor"]

stamps = [datetime.strptime(t["createdAt"], "%a %b %d %H:%M:%S %z %Y") for t in tweets]
print("per month:", sorted(Counter(s.strftime("%Y-%m") for s in stamps).items()))
print("per hour :", sorted(Counter(s.hour for s in stamps).items()))
05 — Section

The full TweetStats replacement script

The script at the bottom of this page does the rest. It walks a date range one month at a time (smaller queries are easier to retry), then produces a four-panel PNG (timeline, weekday, hour, density heatmap), a CSV of every tweet for your own analysis, and printed top-10 lists for @replies, interface used, reposts, TweetCloud and HashCloud.

It needs requests and matplotlib, plus a TWITTERAPI_IO_KEY environment variable. Change HANDLE, START and END at the top. Reposts are counted only where the search results include them (they carry a retweeted_tweet object), and they're left out of the TweetCloud so other people's words don't fill your cloud.

06 — Section

Cost: TwitterAPI.io vs the official X API

TweetStats was free because it ran on Twitter's free API. Today both data routes are paid per tweet read. Prices: twitterapi.io/pricing lists $0.15 per 1,000 tweets; docs.x.com pay-per-use pricing lists $0.005 per post read. The account sizes below are example inputs.

Graph jobTweets readTwitterAPI.ioOfficial X API (pay-per-use)
1 month, account posting ~10 per day~300~$0.05~$1.50
1 year, account posting ~10 per day~3,650~$0.55~$18.25
1 year, heavy poster at ~50 per day~18,250~$2.74~$91.25
1 year each for 10 accounts at ~10 per day~36,500~$5.48~$182.50
Setup before the first request—API key in one headerDeveloper account, app, bearer token

The ratio is $0.005 ÷ $0.00015 ≈ 33× per tweet. The X API user-posts timeline also only accepts start_time values on or after 2010-11-06 (docs.x.com), while search-based pulls work by date window.

Log-scale dumbbell chart comparing the cost of four TweetStats-style graph jobs on TwitterAPI.io versus the official X API pay-per-use tier
Same four jobs as the table: $0.05 vs $1.50 up to $5.48 vs $182.50 — a ~33× gap at every size.
07 — Section

Which TweetStats alternative fits you?

Your situationUseWhy
Impressions and clicks on your own postsX's built-in analyticsOnly the owner can see those metrics
Your own full tweet history, onceX data archive downloadFree and complete for your account
TweetStats graphs for any public accountThe script on this pageRebuilds all nine views from tweet fields
Graphs refreshed every monthSame script on a scheduleEach run re-reads only the window you set
Engagement metrics rather than posting habitsTwitter stats API guideCovers likes, reposts, views per tweet

If you collect other people's tweets for research or publication, check X's developer terms and your organization's data policy first.

python
# TweetStats-style graphs for any public X account: tweet timeline, tweets per
# weekday and hour, density heatmap, top @replies, posting clients, reposted
# accounts, TweetCloud and HashCloud, saved as tweetstats_<handle>.png + .csv
import os, re, csv, requests
from collections import Counter
from datetime import datetime, timezone
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt

HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
HANDLE = "nasa"
START, END = (2025, 10), (2026, 9)  # inclusive (year, month)
STOP = set("the a an and or to of in on for is it at be this that with i you my me we our are was rt https co amp".split())

def months(start, end):
    y, m = start
    while (y, m) <= end:
        yield y, m
        y, m = (y + 1, 1) if m == 12 else (y, m + 1)

def month_bounds(y, m):
    lo = datetime(y, m, 1, tzinfo=timezone.utc)
    hi = datetime(y + (m == 12), m % 12 + 1, 1, tzinfo=timezone.utc)
    return int(lo.timestamp()), int(hi.timestamp())

def fetch_month(y, m):
    lo, hi = month_bounds(y, m)
    query = f"from:{HANDLE} since_time:{lo} until_time:{hi}"
    cursor, out = "", []
    while True:
        r = requests.get(
            "https://api.twitterapi.io/twitter/tweet/advanced_search",
            headers=HEADERS,
            params={"query": query, "queryType": "Latest", "cursor": cursor},
            timeout=20,
        )
        r.raise_for_status()
        body = r.json()
        out += body.get("tweets", [])
        if not body.get("has_next_page"):
            return out
        cursor = body["next_cursor"]

tweets = [t for y, m in months(START, END) for t in fetch_month(y, m)]
for t in tweets:
    t["_dt"] = datetime.strptime(t["createdAt"], "%a %b %d %H:%M:%S %z %Y")

per_month = Counter(t["_dt"].strftime("%Y-%m") for t in tweets)
per_weekday = Counter(t["_dt"].weekday() for t in tweets)
per_hour = Counter(t["_dt"].hour for t in tweets)
density = [[0] * 24 for _ in range(7)]
for t in tweets:
    density[t["_dt"].weekday()][t["_dt"].hour] += 1
replied_to = Counter(t.get("inReplyToUsername") for t in tweets if t.get("isReply") and t.get("inReplyToUsername"))
clients = Counter(t.get("source") or "unknown" for t in tweets)
reposted = Counter(((t.get("retweeted_tweet") or {}).get("author") or {}).get("userName")
                   for t in tweets if t.get("retweeted_tweet"))
reposted.pop(None, None)
hashtags = Counter(h["text"].lower() for t in tweets for h in (t.get("entities") or {}).get("hashtags") or [])
words = Counter(w for t in tweets if not t.get("retweeted_tweet")
                for w in re.findall(r"[a-z']{3,}", re.sub(r"https?://\S+|@\w+|#\w+", "", t.get("text", "").lower()))
                if w not in STOP)

fig, ax = plt.subplots(2, 2, figsize=(14, 9))
labels = [f"{y}-{m:02d}" for y, m in months(START, END)]
ax[0][0].bar(labels, [per_month[k] for k in labels], color="#1d9bf0")
ax[0][0].set_title("Tweet timeline (per month)")
ax[0][0].tick_params(axis="x", rotation=60)
ax[0][1].bar(["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], [per_weekday[d] for d in range(7)], color="#1d9bf0")
ax[0][1].set_title("Tweets per weekday (UTC)")
ax[1][0].bar(range(24), [per_hour[h] for h in range(24)], color="#1d9bf0")
ax[1][0].set_title("Tweets per hour (UTC)")
im = ax[1][1].imshow(density, aspect="auto", cmap="Blues")
ax[1][1].set_yticks(range(7), ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"])
ax[1][1].set_title("Tweet density (weekday x hour, UTC)")
fig.colorbar(im, ax=ax[1][1])
fig.suptitle(f"TweetStats-style graphs for @{HANDLE}: {len(tweets)} tweets")
fig.tight_layout()
fig.savefig(f"tweetstats_{HANDLE}.png", dpi=120)

with open(f"tweetstats_{HANDLE}.csv", "w", newline="") as f:
    w = csv.writer(f)
    w.writerow(["id", "createdAt", "isReply", "inReplyToUsername", "source", "likeCount", "retweetCount", "viewCount", "text"])
    for t in tweets:
        w.writerow([t["id"], t["createdAt"], t.get("isReply"), t.get("inReplyToUsername"), t.get("source"),
                    t.get("likeCount"), t.get("retweetCount"), t.get("viewCount"), t.get("text")])

for title, c in [("Top @replies", replied_to), ("Interface used", clients), ("Reposts of", reposted),
                 ("TweetCloud", words), ("HashCloud", hashtags)]:
    print(f"{title}: " + ", ".join(f"{k} ({v})" for k, v in c.most_common(10)))
print(f"{len(tweets)} tweets, approx cost ${len(tweets) * 0.00015:.2f}")
08 — Questions

Questions readers ask

Is TweetStats still working?

No. www.tweetstats.com now shows a memorial page reading "In memory of TweetStats, January 2008 - February 2023". Its creator shut it down when Twitter's free API access ended.

Who made TweetStats?

Damon Cortesi (@dacort). According to his memorial page, he launched it in January 2008 and the first version scraped the Twitter website because the API didn't exist yet.

What did TweetStats show?

A tweet timeline by month, tweets per weekday and per hour, a weekday-by-hour density chart, the accounts you replied to most, the apps you tweeted from, whose tweets you retweeted, and word and hashtag clouds.

How can I see my tweets per hour now?

Pull your tweets with their createdAt timestamps and count them by hour, converting from UTC to your timezone first. The script on this page does this for any public account and saves the chart as a PNG.

Can I get TweetStats-style graphs for someone else's account?

Yes, for public accounts. Posting times, reply targets, hashtags and engagement counts are public. X's built-in analytics only covers your own account.

How much does it cost to graph a year of tweets?

For an account posting about 10 times a day, roughly 3,650 tweets: about $0.55 on TwitterAPI.io at $0.15 per 1,000 tweets, versus about $18.25 on the official X API at $0.005 per post read.

09 — Further reading

Continue

Sources & further reading
More from this series
Build it

Stop reading. Start building.

Starter credits cover real testing on real data. Google sign-in, no card, no application queue.

Get an API key
    TweetStats Alternative: Graph Your Tweets | TwitterAPI.io