Use curl-x as an API: No Key, No Login, No Watermark
curl-x has no signup and no API key. Fetch a post URL with curl for a direct file, or POST to /api/extract for structured JSON — here's the real request/response shape, error codes, and rate limits.
Want to try it now? Paste a post link from any supported platform to download its media instantly.
Open Downloadercurl-x has no signup, no API key, and no watermark. There are two ways to use it programmatically: fetch a public post URL with a CLI client (curl -L -o video.mp4 https://www.curl-x.com/<user>/status/<id>) and get the media file back directly, or POST a URL to /api/extract for structured JSON with every available media variant. Both are free, unauthenticated, and rate-limited per IP rather than per key.
Table of contents
- The zero-key pattern: fetch a post URL, get the file
- Which platforms and paths support it
- POST /api/extract for structured JSON
- Error codes
- Rate limits and being a good citizen
- For AI agents
- FAQ
- Bottom line
The zero-key pattern: fetch a post URL, get the file
curl-x doesn't front a "download API" behind an API key. Instead, every supported post has a normal HTML page and a sibling route that streams the raw media. Middleware inspects the request's User-Agent; if it matches a known CLI download client, the request gets rewritten to that sibling route instead of the HTML page — no separate endpoint to learn, no auth header to attach:
curl -L -o video.mp4 https://www.curl-x.com/NASA/status/1234567890123456789
That's a complete, working download command. -o video.mp4 names the saved file explicitly; if you'd rather curl-x name it for you from the response headers (recommended — the suggested name embeds the post ID), use -OJ instead, as covered in how to download a Twitter video with curl. The CLI rewrite happens on an internal path match, not an HTTP redirect, so -L is harmless but not required here.
The trick only fires for clients whose User-Agent contains one of a small allowlisted set: curl, wget, httpie, aria2, axel, lftp. A browser or an HTTP library that doesn't identify as one of these gets the normal HTML page instead — set your client's User-Agent explicitly if you're wrapping curl-x in something else.
Which platforms and paths support it
The CLI rewrite is wired up on one bare "detail" path per platform, each with its own /download sibling route:
| Platform | Path pattern |
|---|---|
| Twitter / X | /<username>/status/<tweetId> |
| Instagram post | /instagram/<shortcode> |
| Instagram reel | /instagram/reel/<shortcode> |
| Threads | /threads/<code> |
| Facebook video | /video/<id> |
| Facebook photo | /photo/<id> |
| Facebook reel | /reel/<id> |
| Reddit post | /r/<subreddit>/comments/<postId> |
| Reddit gallery | /gallery/<postId> |
| TikTok | /tiktok/<id> |
| Bluesky | /bluesky/<actor>/<rkey> |
Every one of these resolves to the post's primary media item — the first photo or video on a multi-item post — as a single file with a proper Content-Disposition: attachment filename. There's no path for pulling every item off a multi-photo or multi-image post through the CLI shortcut; for that, use the structured JSON endpoint below, or the web UI's picker, and see batch-downloading tweet videos with a shell script for scripting a list of posts.
POST /api/extract for structured JSON
When you need every available media variant — not just the one file the CLI shortcut streams — call the extraction API directly:
curl -X POST https://www.curl-x.com/api/extract \
-H "Content-Type: application/json" \
-d '{"url": "https://x.com/NASA/status/1234567890123456789"}'
url accepts a public post link from any supported platform (Twitter/X, Facebook, Instagram, Threads, Reddit, TikTok, Bluesky) — curl-x detects which platform it is from the URL shape itself, so there's no separate endpoint or platform parameter. A successful response looks like:
{
"tweetUrl": "https://x.com/NASA/status/1234567890123456789",
"author": "NASA",
"text": "Some caption text from the post",
"media": [
{
"type": "video",
"thumbnailUrl": "https://pbs.twimg.com/ext_tw_video_thumb/…/img/thumb.jpg",
"variants": [
{
"url": "https://video.twimg.com/ext_tw_video/…/vid/avc1/1280x720/clip.mp4",
"bitrate": 2176000,
"contentType": "video/mp4",
"width": 1280,
"height": 720
}
],
"aspectRatio": 1.7777
}
],
"platform": "twitter"
}
media is an array of items (a multi-photo or multi-video post returns more than one), and each item's variants array lists every downloadable rendition of that item with its own url, contentType, and (when known) bitrate, width, and height — pick whichever variant fits your use case, or just take the first (curl-x already orders them best-first). A Twitter/X response also includes an article field when the tweet links an X Article; other platforms omit it. A Twitter GIF comes back as "type": "gif" with a video/mp4 variant — X converts uploaded GIFs to looping video internally, so that's the file you'll fetch even though the post reads as a GIF.
Each variant's url is a real CDN link (video.twimg.com, pbs.twimg.com, fbcdn.net, cdninstagram.com, and similar per platform) that you can fetch yourself, or hand to curl-x's own generic proxy (GET /api/download?url=<variant-url>) if you want the same attachment headers and suggested filename the per-post download routes produce.
Error codes
A failed request returns a JSON body shaped { "error": "<message>", "code": "<CODE>" } with one of these HTTP statuses:
code | HTTP status | Meaning |
|---|---|---|
INVALID_INPUT | 400 | Request body missing a string url field |
INVALID_URL | 400 | URL doesn't match any supported platform/post pattern |
PARSE_ERROR | 400 | URL matched a platform but couldn't be parsed into a post reference |
NOT_FOUND | 404 | Post doesn't exist, was deleted, or is private/suspended |
RATE_LIMITED | 429 | Upstream platform rate-limited curl-x's extraction (may include a retryAfter field and Retry-After header) |
NETWORK_ERROR | 502 | Upstream fetch failed (timeout, connection error) |
EXTRACTION_FAILED | 422 | Post loaded but no supported media could be extracted from it |
UNKNOWN | 500 | Unclassified server error |
Branch on code, not the human-readable error string — the message text is localized to the caller's Accept-Language/curlx-locale cookie and can change wording, but the code values are stable.
Rate limits and being a good citizen
curl-x runs a per-IP, fail-open rate limiter at the edge with two buckets:
- 60 requests/minute across every
/api/*path and every/download-suffixed route (the global bucket) - 20 requests/minute specifically for
/api/extract(a stricter sub-bucket — those requests also count against the global 60)
Go over either bucket and you get 429 Too Many Requests with a Retry-After: 60 header instead of a result. There's no per-key quota to negotiate for more headroom — the limiter is IP-based and the same for every caller, key or no key. For scripted or agentic use, space out requests (a couple of seconds between calls comfortably clears both buckets) and treat a batch of URLs as a personal-scale job — tens of posts, not an unattended crawl of an entire account's history. The same etiquette from batch-downloading tweet videos with a shell script applies whether you're driving curl-x from a shell loop or an agent's tool-call loop.
For AI agents
If you're building or operating an agent that needs to fetch social media, curl-x's llms.txt is a machine-readable summary of what the site supports — platforms, URL formats, and the /api/extract and /api/download endpoints — meant to be fetched directly instead of scraped from the HTML site. For a ready-to-use operating pattern (when to call curl-x, how to convert a post URL, how to handle private/deleted posts), see how to use an agentic SKILL.md with curl-x. Both are free to fetch and require no registration, matching everything else described here.
FAQ
Does curl-x have an API?
Yes, in two forms: fetching a post's bare URL (e.g. /username/status/tweetId) with a CLI client like curl or wget streams the media file directly, and POST /api/extract with {"url": "..."} returns structured JSON listing every media item and variant for that post.
Do I need an API key?
No. curl-x has no signup, no account, and no API key for either the CLI download path or /api/extract. Requests are identified and rate-limited by IP address only.
What are the rate limits?
60 requests per minute per IP across all /api/* and /download-suffixed routes, with a stricter 20 requests per minute specifically on /api/extract. Exceeding either returns 429 with a Retry-After: 60 header.
Does curl-x add watermarks?
No. curl-x streams the platform's original media file as-is — no overlay, no branding, no watermark added — and it's free to use for public posts.
How do I get a Twitter GIF from a URL?
Use the same /api/extract call or the CLI download path as for a video. Twitter/X converts uploaded GIFs into looping MP4 video internally, so the response's media item comes back with "type": "gif" but a video/mp4 variant — that's the actual file you'll receive, and it plays like a normal video file.
Can I call /api/extract for platforms other than Twitter/X?
Yes. The same endpoint accepts public post URLs from Facebook, Instagram, Threads, Reddit, TikTok, and Bluesky — curl-x detects the platform from the URL itself, so there's no separate endpoint per platform.
Bottom line
curl-x's "API" is deliberately unglamorous: no key to request, no dashboard, no quota tier to upgrade. Fetch a post's bare URL with curl/wget for the file directly, or POST /api/extract when you need every variant's URL, dimensions, and bitrate as JSON. Stay under 20 requests/minute on /api/extract and 60/minute overall, branch on the code field for errors, and — whether you're scripting this by hand or wiring it into an agent via llms.txt — you get the same free, no-login, no-watermark result either way.
Related Guides
Batch-Download Tweet Videos With a 5-Line Shell Script
Save a list of public tweet URLs to a text file and pull every video with a short curl loop. Includes a PowerShell version and rate-limit etiquette.
How to Download a Twitter Video With curl (One Command)
Fetch a Twitter/X post URL with curl and get the actual MP4 back — no browser, no API key. One command, real filename, works with wget too.
Does Twitter Use HLS? How to Find the m3u8 Video URL
Yes — X streams tweet video as HLS (.m3u8 playlists) on video.twimg.com alongside progressive MP4 renditions. Learn to spot the m3u8 in DevTools and why curl-x resolves it to a direct MP4.