Skip to main content
X Articles are long-form posts on the platform - think blog posts published directly on X, with a cover image, rich text, and their own engagement metrics. They are distinct from regular tweets: they have a preview_text (the snippet shown in the timeline), a full_text (the complete article body), a cover image, and a publication date separate from the tweet creation timestamp. The Sorsa /article endpoint retrieves the full content and metadata of any public X Article in a single request.

Simplest Example

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"}'
import requests

API_KEY = "YOUR_API_KEY"

def get_article(tweet_link):
    resp = requests.post(
        "https://api.sorsa.io/v3/article",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return resp.json()


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']:,}")
print(f"Preview: {article['preview_text'][:100]}...")
print(f"Full text length: {len(article['full_text'])} characters")

Endpoint Reference

POST /v3/article

Request Body

ParameterTypeRequiredDescription
tweet_linkstringYesFull URL of the tweet containing the article.

Response

{
  "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.\nthe old model was simple...",
  "cover_image_url": "https://pbs.twimg.com/media/G-t2hYTaIAAstc8.jpg",
  "published_at": "2026-01-15T16:24:02Z",
  "views": 36538,
  "favorite_count": 315,
  "bookmark_count": 38,
  "quote_count": 37,
  "reply_count": 80,
  "retweet_count": 41,
  "author": {
    "id": "1934538036466810880",
    "username": "SorsaApp",
    "display_name": "Sorsa",
    "description": "Crypto social analytics made simple...",
    "followers_count": 6050,
    "verified": false
  }
}

Response Fields

FieldDescription
full_textThe complete article body. Can be thousands of characters long.
preview_textThe truncated snippet shown in the X timeline before a user clicks “Read more.”
cover_image_urlURL of the article’s cover/header image. May be null if no cover was set.
published_atISO 8601 timestamp of when the article was published.
viewsTotal view count.
favorite_countNumber of likes.
bookmark_countNumber of bookmarks.
quote_countNumber of quote tweets.
reply_countNumber of replies.
retweet_countNumber of retweets.
authorFull author profile object (same fields as the standard User object).
Note that the engagement field names in the Article response use slightly different keys than the standard Tweet object: favorite_count instead of likes_count, and views instead of view_count.

Detecting Whether a Tweet Is an Article

Not every tweet link points to an article. If you pass a regular tweet URL to the /article endpoint, the response may differ from what you expect. To determine whether a tweet is an article before calling this endpoint, you can first fetch it via /tweet-info and check for article indicators in the response. In practice, X Articles are recognizable by their URL pattern and by the presence of long-form content that exceeds the standard tweet character limit. If you are building a pipeline that processes mixed content (regular tweets and articles), handle both cases:
def get_content(tweet_link):
    """Fetch a tweet or article, returning the appropriate data."""
    # Try as article first
    try:
        article = get_article(tweet_link)
        if article.get("full_text") and len(article["full_text"]) > 500:
            return {"type": "article", "data": article}
    except Exception:
        pass

    # Fall back to regular tweet
    resp = requests.post(
        "https://api.sorsa.io/v3/tweet-info",
        headers={"ApiKey": API_KEY, "Content-Type": "application/json"},
        json={"tweet_link": tweet_link},
    )
    resp.raise_for_status()
    return {"type": "tweet", "data": resp.json()}

Practical Uses

Content analysis. X Articles are often used for project announcements, thought leadership, and detailed updates. Extracting full_text gives you the complete content for NLP processing, summarization, or archiving - without needing to scrape the X web interface. Engagement benchmarking. Compare article performance metrics across competitors or across your own articles over time. Articles tend to have different engagement patterns than regular tweets (higher bookmark rates, lower retweet rates), so benchmarking them separately is more accurate. Archiving and indexing. Build a searchable archive of articles published by accounts you track. The full_text + published_at + author fields give you everything needed for a content database.
# Collect and compare articles from multiple accounts
def compare_article_performance(article_links):
    for link in article_links:
        a = get_article(link)
        author = a["author"]["username"]
        print(f"@{author} | {a['published_at'][:10]} | "
              f"Views: {a['views']:,} | Likes: {a['favorite_count']:,} | "
              f"Bookmarks: {a['bookmark_count']:,} | "
              f"Text: {a['preview_text'][:60]}...")

Next Steps