How to Track Andrew Tate's Tweets Using the Twitter (X) API

By Sarah Wong•8 min read

Andrew Tate (X handle @cobratate) is one of the most controversial and most-watched influencer accounts on X — a former kickboxer turned controversial commentator whose account was banned in 2022 and reinstated in 2023, and which routinely produces multi-million-engagement viral tweets when active. For audience-research teams, brand-safety platforms, and culture-watching analysts, the account is both high-value as a signal and high-risk as a tracker: the handle has gone away and come back before and could again.

Programmatically following @cobratate well means more than a timeline scrape — it means a tracker that survives suspensions gracefully, captures the viral-velocity profile that distinguishes a Tate tweet from background noise, and pulls the quote-tweet + reply network where most of the cultural reaction actually lives.

This guide covers the tracking methods, a runnable Python pipeline that handles the suspended/active state machine, and the specific data patterns (viral velocity, reply-sentiment polarization, quote-cluster topology) that make Tate-account data uniquely valuable for downstream products.

01 — Section

Who is Andrew Tate and why @cobratate is operationally tricky to track

Andrew Tate is a former professional kickboxer who became one of the most-discussed influencers on X starting in 2022. His content centers on masculinity, lifestyle, business, and political commentary. His current handle is @cobratate; the original @TateConfidential account is banned. His account has cycled through banned → reinstated states; on X, that cycle is part of what your tracker has to handle.

What makes this account distinctive from a tracking standpoint:

PropertyWhat it means for your pipeline
Viral velocityTop tweets accumulate hundreds of thousands of engagements within the first hour
Suspension riskHandle has gone from active → suspended → active before; when suspended, user/info still answers HTTP 200 but marks the account unavailable in the body
Reply polarizationReplies cluster strongly into pro/anti camps — useful unsupervised polarization signal
Quote-tweet networkEach viral tweet generates a large quote-tweet thread; commentators reuse the original as a rhetorical anchor
Banner-text changesProfile bio and pinned tweet change frequently; track these as discrete events

Implications for the tracker design: you need (a) a suspension-aware state machine so the pipeline doesn't crash when the handle comes back as unavailable, (b) frequent polling immediately after each new tweet to capture engagement velocity at multiple time points (T+5m, T+30m, T+2h, T+24h), and (c) a quote-tweet collection pass on viral tweets so the reaction network is in your dataset, not just the original posts.

02 — Section

Twitter / X API methods for tracking @cobratate

The three architectural patterns for following one account map to Tate-style usage as follows.

1. Timeline polling with velocity-capture (pull) — Standard polling for new tweets, plus an engagement-revisit pass for tweets younger than 24 hours. Cheapest by total call volume; gives you the velocity profile (which is the signal that matters for this account).

2. Real-time filter stream (push) — Subscribe to from:cobratate via WebSocket. Sub-second freshness; useful if you're building an alerting product but expensive in operational complexity (persistent worker required).

3. Webhook callbacks — Each new tweet hits your HTTP endpoint. Operationally simple for serverless deploys; slightly higher per-event cost than the filter stream.

For most analytics use cases: option 1 with the velocity-capture pass is the right starting point. Add option 2 only if your product depends on beating other commentators to publication by 30-60 seconds.

03 — Section

TwitterAPI.io quickstart — pulling @cobratate's timeline

TwitterAPI.io is a third-party X API offering pay-per-call pricing at $0.00015 per read — roughly 33× cheaper than the official X API's $0.005 per post read. Setup is a Google sign-in + an X-API-Key header; no OAuth flow, no X developer account, no monthly minimum.

Endpoints chosen for this guide:

GET /twitter/user/info — resolves @cobratate → user_id; also returns the current banned/active state (a suspended account comes back as HTTP 200 with unavailable: true in the body).

GET /twitter/tweet/advanced_search — with query=from:cobratate since_time:<unix seconds of the newest tweet seen> and queryType=Latest it returns only tweets newer than that timestamp; for the main polling loop. We poll search rather than /twitter/user/last_tweets because a poll with nothing new returns 0 tweets and costs the 15-credit minimum ($0.00015), whereas a last_tweets poll bills every tweet on the page (about 20 tweets, so about $130 a month at 60 seconds).

GET /twitter/tweets?tweet_ids=<id> — re-fetch a specific tweet to capture engagement velocity over time.

GET /twitter/tweet/quotes — pull the quote-tweet thread for a viral tweet (the reaction network).

Authentication: put your API key in the X-API-Key header.

PathAuthenticationPrerequisitesPer-read cost
Official X API4 keys + signed OAuthX developer account + saved payment card$0.005
TwitterAPI.io1 X-API-Key headerGoogle sign-in$0.00015
04 — Section

Code example — a suspension-aware Python tracker

The script below polls search for @cobratate's new tweets (the first run starts from the current time, and each poll then asks for tweets newer than the last one seen), schedules a velocity-revisit pass for each new tweet at T+30m, T+2h, T+24h, and handles the suspension state explicitly: if user/info (checked at startup and then once an hour) reports the account as unavailable (data.unavailable is true in an HTTP 200 response), we flag the account as suspended and back off to a once-per-hour heartbeat check until the handle resolves again.

Implementation notes:

POLL_INTERVAL = 120 — 2-minute base poll. Fine for most analytics uses.

VELOCITY_CHECKPOINTS = [30, 120, 1440] — minutes after first-seen at which we re-fetch each tweet for engagement counts.

SUSPENSION_HEARTBEAT = 3600 — when account is suspended, check hourly via user/info and resume the normal loop when it comes back.

Both the timeline poll and the velocity-revisit pass write to the same JSONL with a kind field (new_tweet vs velocity_checkpoint) so downstream consumers can join cleanly.

05 — Section

Viral velocity, polarization, and quote-network patterns

Three patterns emerge consistently across a few weeks of @cobratate data:

1. Viral velocity has a fast-decay shape. Viral Tate tweets tend to accumulate the majority of their 24-hour engagement within the first 90 minutes — the precise fraction depends on the tweet and the moment, but the rule that engagement concentrates early holds across most viral cases. The slope of likes/minute in the first 15 minutes is commonly used as a leading indicator of final reach, and is usually a stronger signal than text features alone for high-velocity accounts. Calibrate the specific threshold against your own observed data. Capture engagement at T+15m as your headline velocity metric.

2. Reply sentiment is sharply bimodal. Run an off-the-shelf sentiment classifier on the first 500 replies to each viral Tate tweet; the distribution is bimodal (strongly positive + strongly negative) rather than gaussian. The ratio of pro/anti replies is a stable signal that's stable across his viral tweets — and useful for testing whether your sentiment classifier is calibrated, since this is a clean test case.

3. Quote-tweet networks cluster by political topic, not tweet content. Even when a Tate tweet is about lifestyle or business, the quote-tweet commentary clusters by the commentator's political identity — left-wing critics, right-wing endorsers, center-skeptics. Useful for audience-mapping: pull the quote-tweets for 50 Tate tweets, cluster the quoter user_ids, and you have a high-leverage map of the political-commentary network on X.

06 — Section

Operational notes — suspension archives, ToS, cost scaling

Because @cobratate has a history of going from active to suspended and back, three operational notes matter more than they would for a stable account:

Suspension is an event, not an error. Your alerting should distinguish 'API error during fetch' from 'account is suspended.' Suspensions are useful state for downstream products (sentiment analysts, brand-safety teams) and worth surfacing as an explicit event in your data.

Archive your own data assertively. Suspensions can take recent tweets out of public-facing view (re-fetches come back empty even for tweets that existed before suspension). If you want a permanent record, your JSONL is the archive — there's no second-chance API path after the fact.

Cost scales linearly per-account. At the 2-minute base cadence, one Tate tracker makes 720 polls a day = 21,600/month, which is $3.24/month on TwitterAPI.io (21,600 × $0.00015, the minimum charge for a poll that finds nothing new). New tweets add $0.00015 each, each of the 3 velocity checkpoints per new tweet adds another $0.00015, and the hourly account-state check adds 720 profile reads a month at $0.00018 (about $0.13). The same 21,600 calls on the official X API at $0.005/read are $108/month. See our cost-at-volume breakdown for the math at 10/100/1000 accounts.

07 — Section

What this data unlocks for downstream products

A clean @cobratate dataset composes with other sources for several use cases:

Brand-safety scoring — Train a classifier on (Tate-tweet, brand-mention) pairs to flag tweets that mention a brand alongside controversial topics — useful as a real-time signal for brand PR teams who need to react fast.

Audience-overlap discovery — Pull the quoter user_ids across 100 viral Tate tweets, cluster them, and you have a high-resolution map of the political-commentary network. Same technique applied to a basket of accounts yields the full influencer-network graph.

Viral-velocity benchmarking — Use Tate tweets as a high-velocity comparison case for your own product's viral-detection thresholds. If your alerting system doesn't fire on Tate tweets, your sensitivity is too low.

Polarization-signal datasets — The bimodal reply-sentiment distribution makes Tate tweets useful as ground-truth examples in polarization-research training data. Most off-the-shelf datasets have weaker signal.

python
# pip install requests
import json
import time
import pathlib
from datetime import datetime
import requests

API_KEY = "YOUR_TWITTERAPI_IO_KEY"
BASE = "https://api.twitterapi.io"
HANDLE = "cobratate"
POLL_INTERVAL = 120                       # 2 min base
SUSPENSION_HEARTBEAT = 3600               # 1 h while suspended
VELOCITY_CHECKPOINTS = [30, 120, 1440]    # minutes after first-seen

STATE_DIR = pathlib.Path(".state")
STATE_DIR.mkdir(exist_ok=True)
IDS_FILE = STATE_DIR / "cobratate_seen_ids.json"
VEL_FILE = STATE_DIR / "cobratate_velocity_queue.json"
OUT_FILE = STATE_DIR / "cobratate_events.jsonl"
SINCE_FILE = STATE_DIR / "cobratate_since_time.json"

headers = {"X-API-Key": API_KEY}


def load_json(p, default):
    return json.loads(p.read_text()) if p.exists() else default


def save_json(p, obj):
    p.write_text(json.dumps(obj))


def append_event(d):
    with OUT_FILE.open("a") as f:
        f.write(json.dumps(d) + "\n")


def account_active(handle):
    r = requests.get(f"{BASE}/twitter/user/info",
                     params={"userName": handle}, headers=headers, timeout=10)
    r.raise_for_status()  # user/info answers HTTP 200 either way; the outcome is in the body
    body = r.json()
    data = body.get("data") or {}
    if body.get("status") != "success" or data.get("unavailable"):
        return False  # not found, or suspended (data["unavailableReason"])
    return True


def enqueue_velocity_checkpoints(tid, first_seen):
    q = load_json(VEL_FILE, [])
    for minutes in VELOCITY_CHECKPOINTS:
        q.append({"tid": tid, "at": first_seen + minutes * 60})
    save_json(VEL_FILE, q)


def due_velocity_checkpoints(now):
    q = load_json(VEL_FILE, [])
    due = [x for x in q if x["at"] <= now]
    remaining = [x for x in q if x["at"] > now]
    save_json(VEL_FILE, remaining)
    return due


def fetch_tweet_info(tid):
    r = requests.get(f"{BASE}/twitter/tweets",
                     params={"tweet_ids": tid}, headers=headers, timeout=10)
    r.raise_for_status()
    tweets = [t for t in r.json().get("tweets", []) if t.get("id")]
    return tweets[0] if tweets else None  # not returned (or empty id) = deleted or hidden


def to_unix(created_at):
    # createdAt looks like "Tue Oct 13 16:42:56 +0000 2026"
    return int(datetime.strptime(created_at, "%a %b %d %H:%M:%S %z %Y").timestamp())


def poll_once():
    # Ask only for tweets newer than the last one we saw. A poll with nothing
    # new returns 0 tweets and is billed the 15-credit minimum ($0.00015).
    since = load_json(SINCE_FILE, int(time.time()))  # first run: start from now
    r = requests.get(f"{BASE}/twitter/tweet/advanced_search",
                     params={"query": f"from:{HANDLE} since_time:{since}",
                             "queryType": "Latest"},
                     headers=headers, timeout=10)
    r.raise_for_status()
    tweets = r.json().get("tweets") or []
    # next since_time = one second after the newest tweet seen
    save_json(SINCE_FILE, max([since] + [to_unix(t["createdAt"]) + 1 for t in tweets]))
    seen = set(load_json(IDS_FILE, []))
    now = time.time()
    for t in tweets:
        if t["id"] in seen:
            continue
        append_event({
            "kind": "new_tweet", "id": t["id"],
            "created_at": t.get("createdAt"), "text": t.get("text"),
            "likes": t.get("likeCount", 0), "retweets": t.get("retweetCount", 0),
            "replies": t.get("replyCount", 0), "first_seen_at": now,
        })
        enqueue_velocity_checkpoints(t["id"], now)
        seen.add(t["id"])
    save_json(IDS_FILE, sorted(seen))


def velocity_pass():
    for ck in due_velocity_checkpoints(time.time()):
        info = fetch_tweet_info(ck["tid"])
        append_event({
            "kind": "velocity_checkpoint",
            "id": ck["tid"], "at": ck["at"],
            "likes": (info or {}).get("likeCount"),
            "retweets": (info or {}).get("retweetCount"),
            "replies": (info or {}).get("replyCount"),
            "present": info is not None,
        })


if __name__ == "__main__":
    active, last_state_check = False, 0
    while True:
        if not active or time.time() - last_state_check >= SUSPENSION_HEARTBEAT:
            active = account_active(HANDLE)  # one profile read an hour, not one per poll
            last_state_check = time.time()
        if not active:
            append_event({"kind": "suspension_check", "at": time.time(), "present": False})
            time.sleep(SUSPENSION_HEARTBEAT); continue
        try:
            poll_once(); velocity_pass()
        except Exception as e:
            print("err:", e)
        time.sleep(POLL_INTERVAL)
08 — Questions

Questions readers ask

What is Andrew Tate's X / Twitter handle?

@cobratate is the current handle (since 2023 reinstatement). The original @TateConfidential is banned and inaccessible. Double-check the current state with user/info at the start of each pipeline run — handles on X can change state.

Is @cobratate currently active or suspended?

As of 2026 the account is active and posting. Suspensions can recur; treat the active/suspended state as runtime state your pipeline must check, not a static assumption. The signal is in the user/info response body, not the HTTP status: the call returns 200 with data.unavailable set to true and unavailableReason set to Suspended.

How do I capture engagement velocity (not just final counts)?

After your timeline poll captures a new tweet, schedule re-fetches of that tweet at T+30m, T+2h, T+24h via /twitter/tweets. The slope of likes between T+15m and T+30m is a commonly used signal of viral potential — the runnable code above implements this directly via a checkpoint queue. Calibrate the threshold against your own captured data.

What happens to my tracker if @cobratate is suspended?

user/info still returns HTTP 200, with data.unavailable set to true and unavailableReason set to Suspended — treat this as state, not error. Back off to a once-per-hour heartbeat check via user/info, log a suspension_check event, and resume the normal poll loop when the handle resolves again.

Can I get historical Andrew Tate tweets via the API?

Use TwitterAPI.io's advanced_search with from:cobratate since:YYYY-MM-DD until:YYYY-MM-DD. The catch: tweets posted under the previously-banned handle (@TateConfidential) are no longer accessible via any X-API surface. For pre-ban content, only third-party snapshot archives (with their own legal and accuracy caveats) help.

Is it legal to programmatically monitor a public X account?

Programmatic access to public tweets via the X API (official or third-party) is governed by the API's Terms of Service, not by per-account consent — public posts are available for public consumption and analysis under those terms. Note: this is access to public data only; protected/private accounts are excluded. For downstream commercial use (brand-safety products, analytics platforms), consult your jurisdiction's data-protection regulations.

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