Export Twitter (X) Following List — API Tutorial

By Sarah Wong•3 min read

Exporting a Twitter (X) account's full following list is one of the classic API workflows — analytics workflows, backup for account owners, competitive-intel / audience analysis, following-graph research. This tutorial walks the exact call + pagination pattern + honest cost per provider.

Pricing references URL-cited to each provider.

01 — Section

Two API paths — same shape, different pricing

twitterapi.io /twitter/user/followings — cursor-paginated. Returns the accounts the target user follows. Per twitterapi.io/pricing: $0.00001-$0.00003 per follower entry (tiered by page size: 3 credits per user for pages of 1-99, 2 for 100-199, 1 for 200 and more; 100,000 credits = $1; minimum 15 credits per call).

X official /2/users/{id}/following — same data, cursor-paginated. Per docs.x.com/x-api/getting-started/pricing: $0.010 per user in the returned page.

Cost ratio for the same data: $0.010 / $0.00003 = 333x cheaper on twitterapi.io at the smallest page size, $0.010 / $0.00002 = 500x at 100-199 per page, and $0.010 / $0.00001 = 1,000x at 200 or more per page. Choice depends mostly on whether you're already authenticated to X's Developer Console.

02 — Section

Runnable — twitterapi.io export to JSONL

Auth via X-API-Key header. Cursor loops until exhausted.

python
import os, requests, json
from pathlib import Path

HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"

def export_following(handle: str, out_path: str = None):
    if out_path is None: out_path = f"{handle}_following.jsonl"
    Path(out_path).parent.mkdir(exist_ok=True, parents=True) if Path(out_path).parent != Path('.') else None

    following, cursor = 0, None
    with open(out_path, "w") as f:
        for _ in range(200):  # safety cap; 200 pages × 200 = 40,000 following
            params = {"userName": handle, "pageSize": 200}
            if cursor: params["cursor"] = cursor
            r = requests.get(f"{BASE}/twitter/user/followings", headers=HEADERS, params=params, timeout=30)
            r.raise_for_status()
            resp = r.json()
            for user in resp.get("followings", []):
                f.write(json.dumps(user) + "\n")
                following += 1
            cursor = resp.get("next_cursor")
            if not cursor: break
    return following

n = export_following("nasa")
print(f"exported {n} following to nasa_following.jsonl")
# Cost: pages of 200 or more bill 1 credit per entry = n × $0.00001 (minimum 15 credits per call)
03 — Section

Convert to CSV for spreadsheet analysis

JSONL is great for storage; CSV is what most analysts open. Simple conversion:

python
import json, csv

def jsonl_to_csv(jsonl_path: str, csv_path: str):
    with open(jsonl_path) as jf, open(csv_path, "w") as cf:
        writer = csv.DictWriter(cf, fieldnames=["userName", "name", "followers_count", "following_count", "verified", "description"])
        writer.writeheader()
        for line in jf:
            u = json.loads(line)
            writer.writerow({
                "userName": u.get("userName", ""),
                "name": u.get("name", ""),
                "followers_count": u.get("followers_count", 0),
                "following_count": u.get("following_count", 0),
                "verified": u.get("verified", False),
                "description": (u.get("description", "") or "").replace("\n", " ")[:200],
            })

jsonl_to_csv("nasa_following.jsonl", "nasa_following.csv")
04 — Section

Side-by-side — 2 API paths

Per-entry cost derived from published pricing pages. Page-size affects twitterapi.io pricing tier.

Dimensiontwitterapi.ioX official
Endpoint/twitter/user/followings/2/users/{id}/following
AuthX-API-Key headerBearer + X Dev Console
Per-entry cost$0.00001-$0.00003 tiered (twitterapi.io/pricing)$0.010 (docs.x.com)
Page sizeup to 5000/pagetypically 100-1000/page
Cost @ 1,000 following$0.01-$0.03 (1,000 × $0.00001 to $0.00003)$10.00 (1,000 × $0.010)
Cost @ 10K following$0.10-$0.30 (10,000 × $0.00001 to $0.00003)$100 (10,000 × $0.010)
Best forany following export workflowteams already on X Developer bill

Two practical observations: (a) larger page size (5000) on twitterapi.io reduces per-entry cost tier — use 5000 unless you have a specific reason not to; (b) the gap holds at every volume: $0.010 per user on X official against $0.00001-$0.00003 here is 333x to 1,000x ($0.010 / $0.00003 = 333; $0.010 / $0.00001 = 1,000).

05 — Section

Common export workflows

Account backup (owners): periodic backup of your own following list. Useful before major cleanup or account changes.

Growth tracking: snapshot following list over time — new-follows and unfollows over days/weeks visible as diffs.

Competitive intel: export a competitor's following list to see who they engage with — signals partnerships, hiring targets, industry connections.

Network analysis: export multiple accounts' following lists → construct a follow-graph → cluster analysis / influence-map.

Audience-list discovery: export a high-signal account in your niche → their following list is a curated audience of similar accounts worth engaging.

06 — Section

What the response includes

Each entry in the response is a user object with:

userName: @handle for the followed account.

name: display name.

followers_count: their follower count (useful for filtering by size).

following_count: how many they follow (proxy for account behavior — high-follow accounts differ from low-follow).

verified: verification flag.

description: bio text (often useful for topic-clustering).

created_at: account age (useful to filter out new / bot accounts).

profile_image_url_https: avatar URL.

python
# Practical example: bulk export following lists for multi-account competitive analysis.
import os, requests, json, csv
from pathlib import Path
from collections import Counter

HEADERS = {"X-API-Key": os.environ["TWITTERAPI_IO_KEY"]}
BASE = "https://api.twitterapi.io"
OUT_DIR = Path("following_exports")
OUT_DIR.mkdir(exist_ok=True)

def export_one(handle: str):
    following, cursor = [], None
    for _ in range(200):
        params = {"userName": handle, "pageSize": 200}
        if cursor: params["cursor"] = cursor
        r = requests.get(f"{BASE}/twitter/user/followings", headers=HEADERS, params=params, timeout=30)
        r.raise_for_status()
        resp = r.json()
        following.extend(resp.get("followings", []))
        cursor = resp.get("next_cursor")
        if not cursor: break
    return following

COMPETITORS = ["competitor_a", "competitor_b", "competitor_c"]
following_map = {}
for h in COMPETITORS:
    following_map[h] = export_one(h)
    with open(OUT_DIR / f"{h}.jsonl", "w") as f:
        for u in following_map[h]:
            f.write(json.dumps(u) + "\n")
    print(f"  {h}: exported {len(following_map[h])} following")

# Cross-reference: accounts followed by 2+ competitors = high-signal targets
all_followed = Counter()
for h, following in following_map.items():
    for u in following:
        all_followed[u.get("userName", "")] += 1
common = [(h, c) for h, c in all_followed.items() if c >= 2]
print(f"\nAccounts followed by 2+ competitors: {len(common)}")

# Cost per twitterapi.io/pricing:
#   3 accounts × ~2000 following avg × ~$0.00002 = ~$0.12 total
#   X official equivalent: ~$30 (150x delta)
07 — Questions

Questions readers ask

Can I export another account's following list without following them?

Yes — public account following lists are visible via the API regardless of your follow relationship. Only fully-private accounts gate this data.

Rate limits during large export?

twitterapi.io limits requests per second: 0.2 requests/s for accounts that never paid, 20 once paid, 50 on Scale and 500 on Business (see /qps-limits). For very large exports (accounts following 10K+ accounts), pace requests to your limit rather than bursting. Batch of 5000 per page keeps request count low.

What if the account has recently unfollowed people?

The endpoint returns the current state. Real-time — unfollows since last export won't appear. For diff analysis (who unfollowed / new-follows), snapshot periodically + compare.

Can I get order of following (who they followed first)?

Cursor pagination returns in reverse-chronological (most recent follow first). Persistent across pagination but not documented as a stable ordering guarantee — treat as approximate.

Does exporting following count toward my quota?

Each returned entry counts. 1000 following = 1000 entries billed at the per-entry rate. Larger page sizes (5000) put you in the cheaper tier.

Can I export the reverse — accounts that follow this account?

Yes — that's /twitter/user/followers (same pattern, reversed direction). See /blog/twitter-follower-tracking-api-guide for that workflow.

08 — 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