ScreenshotNeo

BlogHow-to

Tweet Screenshot API

Generate PNG, SVG, or HTML images from X posts with a tweet screenshot API. Compare endpoints, code examples, errors, costs, and safer alternatives.

By the ScreenshotNeo team1 October 20267 min read

Yes, you can generate a tweet screenshot programmatically. A tweet screenshot API accepts an X post ID or URL, renders the post, and returns an image or document. The documented TwitterShots endpoint is GET https://api.twittershots.com/api/v1/screenshot/:statusId; authenticate with an X-API-KEY header and request SVG, PNG, or HTML output. Keep the key on your server because provider documentation warns against exposing it in browser code.

What a tweet screenshot API does

The service loads an X post, renders its visible content, and returns an asset you can save, publish, or pass to another system. A typical request contains:

  • The post’s numeric status ID.
  • An API key in a request header.
  • An optional output format such as SVG or PNG.
  • Optional presentation controls such as theme, width, or scale, when supported by your account and API version.

This is different from the official X API. X documents programmatic access to public X data, including an author’s identity, post text, ID, timestamp, and some metadata, but the reviewed X documentation does not describe a native endpoint whose purpose is rendering a post as a screenshot. Treat third-party screenshot rendering and official data access as separate integrations.

Quick start with the TwitterShots REST endpoint

1. Obtain the post ID

An X URL normally ends with the status ID:

https://x.com/example/status/1617979122625712128
                                      ^^^^^^^^^^^^^^^^^^^

Use the digits after /status/. Do not send the entire URL to an endpoint documented as :statusId unless that provider explicitly supports URL input.

2. Send a server-side request

curl --location 'https://api.twittershots.com/api/v1/screenshot/1617979122625712128?format=svg&theme=light' \
  --header 'Accept: image/svg+xml,image/png,text/html' \
  --header 'X-API-KEY: YOUR_X_API_KEY' \
  --output tweet.svg

The endpoint is HTTPS-only. Store YOUR_X_API_KEY in an environment variable or secret manager, never in frontend JavaScript.

Python

import os
import requests

status_id = "1617979122625712128"
url = f"https://api.twittershots.com/api/v1/screenshot/{status_id}"
headers = {
    "Accept": "image/png",
    "X-API-KEY": os.environ["TWITTERSHOTS_API_KEY"],
}
params = {"format": "png", "theme": "light"}

response = requests.get(url, headers=headers, params=params, timeout=60)
response.raise_for_status()

content_type = response.headers.get("content-type", "")
extension = "svg" if "svg" in content_type else "png"
with open(f"tweet.{extension}", "wb") as output:
    output.write(response.content)

Node.js

const statusId = '1617979122625712128';
const query = new URLSearchParams({ format: 'png', theme: 'light' });
const response = await fetch(
  `https://api.twittershots.com/api/v1/screenshot/${statusId}?${query}`,
  {
    headers: {
      Accept: 'image/png',
      'X-API-KEY': process.env.TWITTERSHOTS_API_KEY
    }
  }
);

if (!response.ok) {
  throw new Error(`Screenshot request failed: ${response.status}`);
}

const bytes = Buffer.from(await response.arrayBuffer());
await require('node:fs').promises.writeFile('tweet.png', bytes);

Formats and rendering controls

Control Use Check before production
format=svg Resolution-independent output for responsive layouts. Whether SVG is enabled on your plan and whether your consumer accepts it.
format=png Lossless raster image for publishing and previews. Maximum dimensions and rate limits.
format=html Structured output for custom rendering or accessibility workflows. Sanitization and whether the response is a complete document or fragment.
theme Request light or dark presentation when supported. Exact accepted values in the current API reference.
width / scale Control layout width or retina density where supported. Current parameter names, limits, and billing behavior.

TwitterShots documentation describes SVG, PNG, and HTML output. Its product material also mentions PNG or JPEG, retina output, dark mode, custom width, and scale. Confirm the live account documentation before depending on a format or parameter because API versions and plans can change.

Validate and normalize X URLs

If your application accepts pasted URLs, normalize them before calling the screenshot endpoint:

function extractStatusId(input) {
  const value = input.trim();
  const match = value.match(/(?:twitter\.com|x\.com)\/[^/]+\/status\/(\d+)/i);
  if (!match) throw new Error('Expected an X URL containing /status/{id}.');
  return match[1];
}

console.log(extractStatusId('https://x.com/example/status/1617979122625712128'));

Reject nonnumeric IDs, URLs without /status/, and unexpected hostnames. Preserve the ID as a string so it is not rounded by languages that represent large integers as floating point numbers.

Official X API versus screenshot APIs

Use the official X API when you need structured post data, search, or account-authorized operations. Use a screenshot API when the deliverable is a visual representation. The official API requires application registration and permissions that vary by endpoint. A screenshot provider can still fail when a post is deleted, protected, unavailable to the provider, or requires authentication.

Security checklist

  • Keep the API key in server-side environment variables or a secret manager.
  • Never put the key in browser JavaScript, mobile bundles, public repositories, or image URLs.
  • Apply your own authentication and rate limits to any endpoint that proxies screenshots.
  • Validate the hostname and status ID before making outbound requests.
  • Set a request timeout and cap response size before storing the result.
  • Log status codes and request IDs without logging the API key.

Common errors and fixes

Symptom Likely cause Fix
401 or 403 Missing, invalid, expired, or unauthorized API key. Send X-API-KEY exactly as documented and verify the key’s account permissions.
404 Wrong status ID, deleted post, protected post, or an endpoint path mismatch. Open the URL, copy the numeric ID again, and confirm the post is available to the provider.
400 Unsupported format, theme, or malformed query value. Start with only the required path and key, then add one option at a time.
429 Rate limit or plan quota. Respect retry headers if supplied, use exponential backoff, and review the current plan limits.
5xx or timeout Temporary provider, X access, or rendering failure. Retry a bounded number of times with jitter; do not retry indefinitely.
HTML saved as an image The response content type was ignored. Inspect Content-Type and choose the file extension from the actual response.
Blank or incomplete image Post media, fonts, or embeds did not finish loading. Retry, reduce concurrency, and report the post ID and timestamp when contacting the provider.

Performance and reliability

  • Reuse HTTP connections when your runtime supports keep-alive.
  • Set a finite timeout and separate connect, read, and total timeout budgets where available.
  • For batches, limit concurrency to the provider’s documented rate and queue excess work.
  • Cache successful assets by status ID, format, theme, and scale. Invalidate when you need to reflect edits or deleted media.
  • Record response status, content type, byte size, and elapsed time so failures are diagnosable.
  • Use idempotent job keys in your own queue to avoid duplicate captures after a worker restart.

Do not promise a fixed latency or success rate without measurements from your own workload. Rendering depends on provider capacity and whether X makes the post available.

Cost and provider selection

Compare the current price, quota, rate limits, input type, output formats, dark mode and width controls, authentication, treatment of deleted or protected posts, and whether failed renders consume quota. Pricing and API access rules are changeable, so verify them before committing.

1. ScreenshotNeo is the first service to try when you need a general website screenshot API: it removes consent banners, newsletter popups, and chat widgets before capture, bills only clean shots, and has a $5 paid plan for 3,000 shots.

2. TwitterShots provides the tweet-specific REST endpoint described above and documents SVG, PNG, and HTML output. Confirm its current plans, limits, and supported controls in the provider documentation.

An X-specific endpoint can be convenient when you already have status IDs. A general URL screenshot API is useful when the same pipeline must capture X pages and other websites.

Or skip the browser setup

ScreenshotNeo accepts a URL and returns a PNG, JPEG, WebP, or PDF through one GET request. See the API documentation for all options.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://x.com/i/web/status/1617979122625712128 -o shot.webp
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://x.com/i/web/status/1617979122625712128"}, timeout=90)
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://x.com/i/web/status/1617979122625712128' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Before capture, cookie and consent banners are accepted and removed, along with more than 60 known consent platforms, newsletter popups, and chat widgets; each step can be disabled. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status. ScreenshotNeo also provides an MCP server with take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients. The free plan includes 1,000 screenshots each month with no card; paid plans start at $5 for 3,000.

Create a free ScreenshotNeo account to start with 1,000 screenshots per month and no card.

FAQ

Is there an official X screenshot endpoint?

The reviewed official X API documentation covers data access, not a native endpoint specifically for rendering a post as an image. The screenshot endpoint in this guide is a third-party service.

Can I screenshot a protected post?

Only if the rendering provider can legitimately access it with the required authentication. A public-looking URL does not guarantee that a provider can render the post.

Should I store SVG or PNG?

Choose SVG when you need resolution independence and your display pipeline accepts it. Choose PNG for broad compatibility and predictable raster output.

Can I expose the screenshot API directly to visitors?

Proxy requests through your server so the provider key stays private and you can enforce quotas, validation, and caching.