By Sorsa Editorial

Updated June 13, 2026: re-verified the X Articles character limit and the January 2026 Premium expansion against current reporting, corrected the prize framing to the January 2026 payout-period contest, and aligned the /article response fields with the current API reference.

Key Takeaway X Articles are long-form posts on X holding up to roughly 100,000 characters, with a cover image and rich formatting. The official X API exposes only a t.co wrapper, not the body. Fetching the full text, cover image, publication date, and engagement metrics takes one dedicated REST call.

Sorsa API, an alternative Twitter/X API provider, closes that gap with a dedicated POST /v3/article endpoint that returns the full article object as JSON in a single request: body text, cover image, publication date, and every engagement metric, with no OAuth, no app review, and no headless browser. Calls are billed flat at one request each, from $49 a month for 10,000 requests, on a 20 requests per second limit that applies on every plan.

Since X opened Articles to all Premium subscribers in January 2026, more journalists, analysts, and project teams publish long-form content natively instead of on Medium or Substack. The catch for anyone building monitoring or analytics: the official X API was never designed around the Articles object, so a standard tweet lookup hands back a short link and nothing else. This guide is a practical reference for working with the X Articles API: what the format is, why the official endpoints fail to return it, and how to pull the full article body, metadata, and metrics in one REST call, with runnable Python for detection, competitor benchmarking, and content analysis.

Table of Contents

What Are X Articles?

X Articles are a native long-form publishing format on X (formerly Twitter) that lets eligible accounts post formatted pieces of up to roughly 100,000 characters, far beyond the 280-character tweet limit. Each Article has a cover image, a title, body text with headings and lists, embedded media, and its own publication date, and it appears under a dedicated Articles tab on the author's profile.

X launched Articles on March 8, 2024, initially for Premium+ subscribers and Verified Organizations. According to Engadget, the cap lands around 100,000 characters, against 25,000 for the separate long posts feature. On January 7, 2026, X head of product Nikita Bier announced the feature's expansion to all Premium subscribers, ending Premium+ exclusivity. Social Media Today reported that X paired the push with a one-time $1 million prize for the top long-form Article of its late-January 2026 payout period, open to US Premium users posting original pieces of at least 1,000 words and judged primarily on Verified Home Timeline impressions.

A few properties matter when you build against this format:

  • Articles carry their own engagement object, with patterns that differ from regular tweets, notably higher bookmark rates and lower retweet rates.
  • The announcement post that links an Article is still an ordinary tweet; the article body lives in a separate object.
  • The publication date of the Article is distinct from the created_at of the announcement tweet.

Why the Official X API Doesn't Return Article Content

The official X API does not expose Article bodies. When an author publishes an Article, X creates an announcement tweet that links to it, and a standard tweet lookup returns only that tweet's text, which contains a t.co short link rather than the article content. Following the link redirects to a rendered web page at x.com/i/article/{id}, not a JSON endpoint, so the body, cover image, and publication date stay out of reach through normal post-read calls.

A standard v2 lookup of the announcement tweet returns something like this:

json
{
  "data": {
    "id": "1234567890",
    "text": "Just published a new piece on the state of crypto Twitter in 2026 https://t.co/XYZ123",
    "edit_history_tweet_ids": ["1234567890"]
  }
}

That t.co link is the whole payload. There is no body, no cover image, no publication date.

The note_tweet field does not solve this. It was added for 25,000-character long posts, a different feature: a single text blob with no formatting, no cover image, no separate publication date, and a ceiling well below the Article limit. Reading note_tweet gives you long-post text, never Article content.

The workarounds teams reach for all involve browser automation: drive a headless browser to the rendered article page with an authenticated cookie and scrape the DOM. That holds up for a one-off, but as a production pipeline it is a standing tax. You run a browser cluster, rotate cookies before they expire, handle challenges, and watch latency climb from milliseconds to seconds. This is the exact gap that sends teams looking for a Twitter API alternative: the data is public, the access pattern should be a REST call, and the official API still leaves you reaching for a browser.

For Article retrieval specifically, the practical comparison is less about price per call and more about whether the body is reachable at all. The table below contrasts a read-only X data API exposing a direct article endpoint with the official X API.

Sorsa APIOfficial X API
Article body accessYes, full text via POST /v3/articleNo, only a t.co wrapper in the tweet text
Cover image and publish dateReturned in the same callNot exposed through post-read endpoints
AuthenticationSingle ApiKey headerOAuth 2.0 or Bearer Token, app review required
SetupMinutes (signup plus key)Days to weeks (developer project approval)
Rate limit20 req/s flat on every planPer-endpoint windows
Cost per article fetch$0.0018 to $0.0049 depending on planBody not available via API; scraping instead
Publishing or writing ArticlesNot supported (read-only)Supported

If you need to publish Articles or write to X, that is the official API's territory, since a read-only X data API does not post. For pulling article content at a flat, predictable price without a scraping stack, a direct article endpoint is the simpler path. Sorsa API is our product, so read the table as a vendor's comparison and test any provider against your own workload before committing.

X Articles vs Long Posts vs Threads

X has three distinct long-form mechanisms, and they are easy to confuse. Regular tweets cap at 280 characters. Long posts (sometimes called extended posts) reach 25,000 characters for Premium subscribers and surface in the API as note_tweet. X Articles are a separate format of up to roughly 100,000 characters with headings, bold and italic text, lists, embedded media, a cover image, and a dedicated profile tab.

FeatureRegular TweetLong Post (Premium)X Article
Max length280 characters25,000 characters~100,000 characters
FormattingNoneNoneHeadings, bold, italics, lists, media
Cover imageNoNoYes
Separate publish dateNoNoYes
Dedicated profile tabNoNoYes (Articles tab)
Official API fieldtextnote_tweet.textNone directly exposed
Returned by /2/tweetsYes, fullyYes, with tweet.fields=note_tweetNo, only a t.co wrapper

The takeaway for anyone building monitoring: regular tweets and long posts are reachable through the standard API with caveats, but Article bodies are not, so they need a dedicated retrieval method.

When You Need Programmatic Access to X Articles

You need to fetch Article objects, not just their announcement tweets, whenever the long-form body itself is the data. The common cases are competitive content intelligence, durable archiving of specific authors, NLP on clean long-form text, engagement benchmarking against regular tweets, and media or journalist monitoring where Articles are a first-class source rather than a scraping afterthought.

Competitive content intelligence. Long-form Articles reveal a company's messaging strategy far more clearly than its short tweet stream, because Articles are deliberate and structured. Pulling competitor Articles weekly and diffing them is a low-effort, high-signal loop. It pairs naturally with a broader competitor analysis workflow.

Archiving and content databases. If your team relies on specific analysts, traders, or founders, a durable archive protects you when a post is edited, deleted, or hidden. The full_text, published_at, and author fields give a searchable store everything it needs, and you can extend the same approach with historical tweet retrieval for older material.

NLP training and analysis. Articles are among the cleanest long-form text on the platform: written, edited, and intentionally structured, which makes them better suited to sentiment work and topic modeling than the noisy short-tweet stream. The broader pattern is in our guide to sentiment and topic analysis.

Engagement benchmarking. Articles skew toward higher bookmark rates and lower retweet rates than tweets, so benchmarking them against regular posts distorts the numbers. Pull Article objects separately and analyze them as their own class, the same way you would approach tweet-level analytics.

Journalist and thought-leader monitoring. With X actively courting writers, journalists publish to Articles more often, so a media monitoring tool needs Article ingestion as a primary source. For sub-minute detection of new Articles from a watchlist, the architecture matches real-time monitoring.

Fetching an X Article: The Endpoint

Retrieving an X Article through a REST API takes one call: send the announcement tweet's URL or numeric ID to an article endpoint, and the response returns the full body text, the preview snippet, the cover image URL, the publication date, and the engagement counts as JSON. No OAuth handshake and no browser rendering are involved; authentication is a single API key in a request header.

On Sorsa, that endpoint is POST /v3/article. The full specification lives in the article endpoint reference.

Request

POST https://api.sorsa.io/v3/article
Content-Type: application/json
ApiKey: YOUR_API_KEY
json
{
  "tweet_link": "https://x.com/SorsaApp/status/1234567890"
}

The tweet_link field accepts the full announcement tweet URL or just the numeric tweet ID.

Response (200)

json
{
  "full_text": "this isn't a cosmetic rebrand. it's a response to how crypto twitter actually works in 2026...",
  "preview_text": "this isn't a cosmetic rebrand. it's a response to how crypto twitter actually works in 2026...",
  "cover_image_url": "https://pbs.twimg.com/media/G-t2hYTaIAAstc8.jpg",
  "published_at": "2026-01-15T16:24:02Z",
  "likes_count": 315,
  "retweet_count": 41,
  "reply_count": 80,
  "quote_count": 37,
  "bookmark_count": 38,
  "views_count": 36538,
  "author": {
    "id": "1934538036466810880",
    "username": "SorsaApp",
    "display_name": "Sorsa",
    "followers_count": 6050,
    "verified": false
  }
}
FieldDescription
full_textComplete article body, often tens of thousands of characters
preview_textTruncated snippet shown in the timeline before "Read more"
cover_image_urlCover image URL, null if no cover was set
published_atISO 8601 publication timestamp, distinct from the announcement tweet's created_at
likes_countLikes
retweet_countRetweets
reply_countReplies
quote_countQuote posts
bookmark_countBookmarks
views_countImpressions
authorFull author profile object

One field-name note worth handling at the edge of your pipeline: the article response uses views_count, while the standard tweet object uses view_count. If you push both through the same code, normalize the key. The full mapping is in the response format reference.

Quickstart

bash
curl -X POST https://api.sorsa.io/v3/article \
  -H "ApiKey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"tweet_link": "https://x.com/SorsaApp/status/1234567890"}'
python
import requests

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.sorsa.io/v3"

def get_article(tweet_link: str) -> dict:
    """Fetch a single X Article by its announcement tweet URL or ID."""
    resp = requests.post(
        f"{BASE_URL}/article",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()


if __name__ == "__main__":
    article = get_article("https://x.com/SorsaApp/status/1234567890")
    print(f"Author:      @{article['author']['username']}")
    print(f"Published:   {article['published_at']}")
    print(f"Views:       {article['views_count']:,}")
    print(f"Body length: {len(article['full_text']):,} chars")

No developer-portal approval and no OAuth dance: authentication is one header. New keys come from the dashboard, and the quickstart guide covers setup end to end.

Detecting Whether a Post Is an X Article

In a live pipeline you rarely have a clean list of article URLs; you have a stream of posts, some regular and some announcement tweets for Articles. The announcement tweet sits at the usual x.com/{username}/status/{id} path, so the URL alone does not identify it. The reliable approach is to attempt the article endpoint first and fall back to a standard tweet lookup when the response lacks a substantial body.

python
import requests
from typing import Literal, TypedDict

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.sorsa.io/v3"

class Content(TypedDict):
    type: Literal["article", "tweet"]
    data: dict

def get_content(tweet_link: str) -> Content:
    """Return an article object if the link is an Article, else the tweet."""
    headers = {"ApiKey": API_KEY, "Content-Type": "application/json"}

    try:
        resp = requests.post(
            f"{BASE_URL}/article",
            headers=headers,
            json={"tweet_link": tweet_link},
            timeout=30,
        )
        if resp.status_code == 200:
            article = resp.json()
            # Articles carry a substantial body. A short or missing
            # full_text means this was not an Article.
            if article.get("full_text") and len(article["full_text"]) > 500:
                return {"type": "article", "data": article}
    except requests.RequestException:
        pass

    resp = requests.post(
        f"{BASE_URL}/tweet-info",
        headers=headers,
        json={"tweet_link": tweet_link},
        timeout=30,
    )
    resp.raise_for_status()
    return {"type": "tweet", "data": resp.json()}

The 500-character threshold works well in practice. To be stricter, also check for cover_image_url or published_at, both Article-specific fields. The single-post lookup here is POST /v3/tweet-info, which returns the standard tweet object.

Benchmarking Competitor Articles

Benchmarking long-form Articles means pulling each one's metrics and normalizing them per view, because raw counts favor accounts with larger audiences. The signals that matter most for Articles are engagement per 1,000 views and bookmark rate per 1,000 views: bookmarks track save-for-later intent, which correlates with depth and authority and barely registers on regular tweets.

python
import requests
from dataclasses import dataclass
from datetime import datetime

API_KEY = "YOUR_API_KEY"
BASE_URL = "https://api.sorsa.io/v3"

@dataclass
class ArticleMetrics:
    author: str
    published_at: datetime
    views: int
    likes: int
    bookmarks: int
    replies: int
    retweets: int
    quotes: int
    body_length: int

    @property
    def engagement_rate(self) -> float:
        """Engagement events per 1,000 views."""
        if self.views == 0:
            return 0.0
        total = self.likes + self.bookmarks + self.replies + self.retweets + self.quotes
        return (total / self.views) * 1000

    @property
    def bookmark_rate(self) -> float:
        """Bookmarks per 1,000 views."""
        if self.views == 0:
            return 0.0
        return (self.bookmarks / self.views) * 1000


def fetch_article_metrics(tweet_link: str) -> ArticleMetrics:
    resp = requests.post(
        f"{BASE_URL}/article",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
        timeout=30,
    )
    resp.raise_for_status()
    a = resp.json()
    return ArticleMetrics(
        author=a["author"]["username"],
        published_at=datetime.fromisoformat(a["published_at"].replace("Z", "+00:00")),
        views=a["views_count"],
        likes=a["likes_count"],
        bookmarks=a["bookmark_count"],
        replies=a["reply_count"],
        retweets=a["retweet_count"],
        quotes=a["quote_count"],
        body_length=len(a["full_text"]),
    )


def benchmark(article_links: list[str]) -> list[ArticleMetrics]:
    results = []
    for link in article_links:
        try:
            results.append(fetch_article_metrics(link))
        except requests.HTTPError as e:
            print(f"Skipping {link}: {e}")
    return sorted(results, key=lambda m: m.engagement_rate, reverse=True)

Building the input list of Article URLs is a separate step: scan each watchlisted account's recent posts and keep the ones whose text is just a t.co link to x.com/i/article. A benchmark over 50 competitor Articles is 50 requests, well inside the entry plan, and running it weekly costs a few hundred requests a month per competitor. For batching patterns and cursor handling, see Optimizing API Usage.

Analyzing Article Content with NLP

Article bodies are well suited to NLP because the text is clean: written, edited, and structured, with far less of the noise that makes short tweets hard to model. You can pass full_text straight into a sentiment or summarization model with little preprocessing. The retrieval and the analysis are separate layers: fetch the article object, then hand its body to whichever model provider you use.

python
import os
import requests

SORSA_KEY = os.environ["SORSA_API_KEY"]

def fetch_article(tweet_link: str) -> dict:
    resp = requests.post(
        "https://api.sorsa.io/v3/article",
        headers={"ApiKey": SORSA_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
        timeout=30,
    )
    resp.raise_for_status()
    return resp.json()


def build_prompt(article: dict) -> str:
    return (
        "Analyze this X Article. Return JSON with: sentiment "
        "(positive, negative, neutral, or mixed), main_topics (3 to 5 tags), "
        "and a 2 to 3 sentence neutral summary.\n\n"
        f"Body:\n{article['full_text']}"
    )

# Pass build_prompt(fetch_article(link)) to the model provider of your choice.

Because a single key handles 20 requests per second, retrieval is rarely the bottleneck; the model layer is. For high throughput, fetch the articles first, then parallelize the analysis against your provider's concurrency limits. This works well as a daily job over an author watchlist.

Pricing and Rate Limits

Each article fetch counts as one request against a monthly quota, regardless of how long the body is: no per-character billing, no surcharge for cover images, no separate rate limit on the endpoint. A 20 requests per second limit applies uniformly, and a single article call is rarely a bottleneck.

PlanMonthly requestsArticles per monthCost per article
Starter ($49)10,00010,000$0.0049
Pro ($199)100,000100,000$0.00199
Enterprise ($899)500,000500,000$0.0018

Most accounts publish less than one Article a week, so fetching every Article from 200 watchlisted authors weekly runs roughly 800 to 2,000 requests a month, well inside the Starter plan with room for other endpoints. Full plan details are on the pricing page, and the per-call economics across the official X API and a flat-rate model are broken down in the current X API pricing guide. If you are moving an existing integration over, the migration path from the official X API maps endpoints and auth changes.

A B2B SaaS competitive-intelligence team, around ten people, wanted to track long-form Articles from roughly 150 to 200 competitor and analyst accounts every week. On the official X API the bodies were simply not reachable, so the realistic alternative was a headless-browser scraping cluster with cookie rotation and challenge handling. Switching to a direct article endpoint turned the job into a few hundred to a couple thousand requests a month, comfortably inside the entry plan, with no scraping infrastructure to keep alive. The win was not a tuned percentage; it was removing a whole maintenance surface for data that should have been a REST call.

Getting Started

The fastest path from zero to a working article fetch:

  1. Paste an article tweet URL into the API Playground to see the JSON response in the browser before writing any code.
  2. Pull an API key from the dashboard and run the curl call above.
  3. Drop the Python get_article function into a notebook to confirm the integration, then add retries on 429 and a persistence layer for production.

Authentication is one ApiKey header, setup takes minutes with no approval queue, and every endpoint shares the same flat 20 requests per second. Plans start at $49 a month for 10,000 requests, and the article endpoint draws from the same quota as the rest of the read API, so adding it to an existing workflow needs no separate integration.

FAQ

Are X Articles available through the official X API?

Not directly. The official X API has no article-specific endpoint, and the tweet that announces an Article contains only a t.co link in its text field, with no body, cover image, or publication date. The note_tweet field covers 25,000-character long posts, a different feature. To retrieve article bodies, you either run browser automation against the rendered page or use a third-party REST API that resolves the article object.

What is the difference between X Articles and long posts?

Long posts (extended posts) are tweets up to 25,000 characters for Premium subscribers; they appear inline with a "Show more" button, with no separate publication date, no cover image, and no formatting. X Articles are a distinct format of up to roughly 100,000 characters with headings, bold and italic text, lists, embedded media, a cover image, and a dedicated Articles tab on the profile. Articles are closer to a Substack post than to a tweet.

How do you fetch the full text of an X Article?

Send the announcement tweet's URL or numeric ID to an article endpoint and read the JSON response. On Sorsa API, POST /v3/article returns the full body, preview text, cover image, publication date, and engagement counts in a single request, authenticated with one ApiKey header and no OAuth. Each call counts as one request from the plan quota.

Can you retrieve X Articles published in the past?

Yes, as long as the Article is still public on X. Articles have a permanent URL once published, so any historical Article is retrievable by its announcement tweet URL or ID. If the author later deletes the Article, the lookup returns a not-found error. For older tweet archives beyond Articles, a dedicated historical retrieval workflow paginates back to an account's first post.

How much does it cost to pull X Article content via API?

On Sorsa API, an article fetch is a single request, priced from $0.0018 to $0.0049 depending on plan, with no per-character surcharge no matter how long the body is. Plans run from $49 a month for 10,000 requests to $899 for 500,000. Fetching a few hundred Articles a week fits inside the entry plan with quota left for other endpoints.

How can you tell whether a post is an X Article before fetching it?

The announcement tweet uses the normal x.com/{username}/status/{id} path, so the URL alone is not a reliable signal. The dependable method is to call the article endpoint first and treat the result as an Article only when full_text is substantial (a 500-character threshold works well); a short or missing body means it was a regular post. The presence of cover_image_url or published_at confirms it.

Reviewed by Keksich, founder of Sorsa, marketer and X API researcher.

This guide draws on hands-on work running Sorsa's /article endpoint in production, the current Sorsa API v3 reference for field and parameter names, and the live response shape of the endpoint itself. The feature timeline and prize details were verified against Engadget's coverage of the March 2024 launch and the roughly 100,000-character limit, and Social Media Today's reporting on the January 2026 Premium expansion and the $1 million Article contest. Endpoint capabilities and pricing reflect Sorsa's published plans. Verified June 13, 2026.