# SnapAny API > One API for social media downloads and transcription: turn any post URL into watermark-free direct download links (video, image, audio) across 1,000+ sites, paginate creator profiles and playlists, and transcribe audio/video with Whisper large-v3 speaker diarization. Pay-as-you-go credits, charged only on success. Base URL: https://api.snapany.com/openapi/v1 — authenticate with `Authorization: Bearer sk_snapany_xxx`; create a key at https://platform.snapany.com/console/keys, then claim 50 free credits in the console. - OpenAPI: https://api.snapany.com/openapi/v1/openapi.json - MCP: https://api.snapany.com/mcp --- # Quickstart Source: https://platform.snapany.com/docs/quickstart Get from a URL to structured media data in under a minute. ## 1. Get your API key Sign in at [platform.snapany.com](https://platform.snapany.com/console/keys) and create an API key. New developers can claim **50 free credits** in the [console](https://platform.snapany.com/console). ## 2. Make your first request ```bash curl -X POST https://api.snapany.com/openapi/v1/extract/post \ -H "Authorization: Bearer sk_snapany_xxx" \ -H "Content-Type: application/json" \ -d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}' ``` ## 3. Read the response ```json { "title": "...", "medias": [{ "media_type": "video", "resource_url": "https://..." }] } ``` Responses contain business data only. Check your remaining credits anytime via [`GET /credits/balance`](https://platform.snapany.com/docs/api#GET/credits/balance) (free) or in the [Console](https://platform.snapany.com/console). ## Next steps - [Authentication](https://platform.snapany.com/docs/authentication) — how API keys work - [Credits & Billing](https://platform.snapany.com/docs/credits) — pricing model - [API Reference](https://platform.snapany.com/docs/api) — full endpoint documentation with try-it - [MCP](https://platform.snapany.com/docs/mcp) — use SnapAny from Claude Code, Codex and other AI agents --- # Authentication Source: https://platform.snapany.com/docs/authentication All API requests are authenticated with a Bearer token: ``` Authorization: Bearer sk_snapany_xxx ``` ## API keys - Create and manage keys at [Console → API Keys](https://platform.snapany.com/console/keys). Up to 5 keys per account. - Keys can be **deleted** at any time — that is how you rotate a leaked key. - Each key's last-used time is shown in the console so you can identify stale keys. ## If a key leaks 1. Create a new key and switch your services to it. 2. Delete the leaked key — it stops working immediately. 3. Check [Credits history](https://platform.snapany.com/console/usage) for unexpected consumption. ## Rate limits 1200 requests per minute per key. Exceeding it returns HTTP `429` with code `rate_limited` — back off and retry. --- # Credits & Billing Source: https://platform.snapany.com/docs/credits SnapAny API uses prepaid credits. **You are only charged for successful calls** — failed extractions and failed transcriptions cost nothing. **Credits never expire** — no validity period, your balance stays available for as long as you need. ## Pricing | API | Cost | | ----------------- | ------------------------------- | | Extract post | 1 credit / call | | Extract playlist | 2 credits / page | | Extract subtitles | 1 credit / call | | Transcription | 4 credits / minute (rounded up) | Transcription credits are **reserved at submission** (duration is known upfront) and **refunded automatically** if the job fails. ## Credit packs | Pack | Price | | ----------------- | ----- | | 9,000 credits | $9.9 | | 50,000 credits | $49 | | 225,000 credits | $199 | | 700,000 credits | $499 | | 1,500,000 credits | $999 | Credits **never expire**. Pay with card (Stripe), WeChat Pay or Alipay in the [Console](https://platform.snapany.com/console). ## Running out of credits - Requests fail with HTTP `402` (code `insufficient_credits`) when your balance is too low. - Balance warning emails are sent when your balance drops below 10,000 / 5,000 / 1,000 / 500 / 0. - Enable **auto top-up** in the [Console](https://platform.snapany.com/console): when your balance falls below your threshold, your saved card is charged automatically. - For custom monitoring, poll [`GET /credits/balance`](https://platform.snapany.com/docs/api#GET/credits/balance) from your own systems — the endpoint is free of charge. --- # Errors Source: https://platform.snapany.com/docs/errors All errors share one JSON shape: ```json { "message": "human readable message", "code": "machine_code", "detail": "optional detail" } ``` ## Common codes | HTTP | Code | Meaning | Fix | | ---- | ---------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | | 400 | _(varies)_ | Business failure | Handle by the `code` field (extraction codes below) — these calls are **not charged** | | 401 | `invalid_api_key` | Missing, malformed or deleted key | Check the `Authorization: Bearer sk_snapany_xxx` header and the key status in [Console → API Keys](https://platform.snapany.com/console/keys) | | 402 | `insufficient_credits` | Balance too low | Top up in the [Console](https://platform.snapany.com/console), or enable auto top-up | | 404 | — | Resource not found (e.g. an invalid job id) | Check the resource `id` returned by the API | | 422 | — | Invalid request parameters | The `detail` field says which parameter failed and why | | 429 | `rate_limited` | Over 1200 requests/min | Back off and retry after a delay | | 500 | — | Server error | Retry later; contact us if it persists | ## Extraction error codes Extraction failures return HTTP `400` with a code from the extraction engine. These are business failures — **no credits are charged**. | Code | Common cause | What to do | | --------------------------- | ----------------------------------------------------- | ------------------------------------------------------ | | `invalid_url` | Malformed link | Fix the URL format | | `unsupported_url` | A valid URL, but not a post/video link | Use the share link of a single post or video | | `unsupported_site` | The site is not supported | Contact us to request it | | `no_subtitles` | The video has no subtitle tracks (HTTP 404) | Fall back to [Transcription](https://platform.snapany.com/docs/transcription) | | `invalid_playlist_url` | Not a channel/profile/playlist link | Use a public channel, profile or playlist URL | | `playlist_not_supported` | A playlist URL was sent to the single-post endpoint | Use `/extract/playlist`, or pass one post URL | | `content_deleted` | The post was deleted or never existed | Nothing to extract | | `user_not_found` | Account deleted, renamed or restricted | Verify the handle | | `no_story` | The account has no active stories | Stories expire after 24h | | `private_content` | Private or follower-only content | Not extractable | | `members_only_content` | Paid or members-only content | Not extractable | | `age_restricted` | The media is age-restricted | Not extractable (see note below) | | `region_restricted` | The media is region-restricted | Not extractable (see note below) | | `not_premiered` | Scheduled content that has not gone live | Retry after the publish time | | `live_stream_not_supported` | Live streams on this site aren't supported yet | Retry once archived as a normal video (see note below) | | `extract_failed` | Site changes, or the content is currently unreachable | Retry later (see note below) | | `retryable` | Transient failure during extraction | Retry after a short delay (see note below) | | `timeout` | The extraction took too long | Retry after a short delay (see note below) | | `unknown` | Unclassified failure | Retry once (see note below) | > `extract_failed`, `retryable`, `timeout` and `unknown` are **transient** — retrying the same URL later can succeed. Every other code is a settled conclusion about the content itself, so retrying will not change the outcome. Codes get added over time, so treat any code you don't recognise as permanent and log it rather than retrying in a loop. If one site keeps returning `extract_failed`, or `unknown` shows up repeatedly, contact us with the request time. > `age_restricted`, `region_restricted` and `live_stream_not_supported` only come up on **a small number of sites**. Age- and region-restricted media usually extracts fine, and live streams are supported on many sites — Twitch and TikTok among them. Getting one of these three means we can't reach that kind of media on **that particular site**; it does not mean we don't support age-restricted media, region-restricted media or live streams. ## Transcription request errors These come back from the submit call (HTTP `400`), before a job is created — nothing is charged. | Code | Common cause | | -------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | | `file_too_large` | Upload over 512 MB, or the file at `file_url` exceeds the limit | | `audio_too_long` | Audio longer than 6 hours | | `unsupported_audio_format` | Audio format not in the supported list, or the duration can't be read | | `download_failed` | We could not fetch `file_url` | | `unsupported_language` | `language` is not a value our provider accepts — omit the field to auto-detect, or pass a language name / ISO code (`english`, `en`, `chinese`, `zh`) | ## Transcription failures A failed job shows `"status": "failed"` with an `error` field when polling, and the reserved credits are refunded automatically. --- # Extract Post Source: https://platform.snapany.com/docs/extract-post [`POST /openapi/v1/extract/post`](https://platform.snapany.com/docs/api#POST/extract/post) — 1 credit per successful call. Supports 1,000+ sites — the most common ones are listed under "Supported sites" below. ```bash curl -X POST https://api.snapany.com/openapi/v1/extract/post \ -H "Authorization: Bearer sk_snapany_xxx" \ -H "Content-Type: application/json" \ -d '{"url": "https://x.com/user/status/123456"}' ``` What the response contains at a glance (fields a site does not provide are omitted): - **Post**: title/text, publish time, canonical URL, stats (views / likes / comments / shares) - **Author**: display name, avatar, follower count, verification status - **medias**: a **directly downloadable URL** for every video / image / audio, with cover image and duration - **variants**: quality/format tiers for videos (resolution, codec, fps, file size, separate audio track), language variants for multi-audio content - **subtitles**: direct subtitle URLs in multiple languages and formats (srt / vtt and more) - **headers**: request headers some sites require for downloading Full schema and a real-shaped response example: [API Reference](https://platform.snapany.com/docs/api#POST/extract/post). Notes: - Media direct URLs are typically short-lived (hours) — download promptly rather than storing the URLs. - Business failures (deleted/private content, unsupported URL) return HTTP `400` with an error code and are **not charged**. ## Downloading the media **Send the returned headers**: when a media carries a `headers` object, send every header **as-is** when downloading — otherwise you may get HTTP `403`. An empty string value is intentional (e.g. an empty `User-Agent`) and must still be sent. ```python import requests media = post["medias"][0] response = requests.get(media["resource_url"], headers=media.get("headers") or {}, stream=True) with open("video.mp4", "wb") as f: for chunk in response.iter_content(1 << 20): f.write(chunk) ``` **Pick a quality variant**: video `variants` are sorted by `quality` (resolution height; `9999` means original quality and sorts first). Pick the closest tier at or below your target: ```javascript const variants = media.variants ?? [] const target = 1080 const pick = variants.filter(v => v.quality <= target).sort((a, b) => b.quality - a.quality)[0] ?? variants.at(-1) ``` **Merge separate audio/video streams**: when a variant has **both** `video_url` and `audio_url`, they are separate streams. Download both, then merge with ffmpeg — stream copy, no re-encode, takes seconds. If only one URL is present, it is already a complete file. ```bash ffmpeg -i video.mp4 -i audio.m4a -c copy merged.mp4 ``` ## Supported sites YouTube, TikTok, Instagram, X/Twitter, Facebook, Threads, Reddit, Pinterest, Tumblr, Vimeo, Dailymotion, VK, OK.ru, Twitch, Likee, Kwai, Suno, Sora, bilibili.tv, Xiaohongshu (RED), Bilibili, Weibo, WeChat official accounts & Channels, Toutiao / Xigua Video, Haokan Video, Tencent Video, iQIYI, Migu Video, Sohu Video, CCTV, NetEase Cloud Music, Qishui Music, WeSing, Weishi, AcFun, Huoshan, Pipixia, Pipi Gaoxiao, Zuiyou, Pear Video, Hongguo Duanju, Jianying (CapCut CN), Jimeng, Doubao, Meipai, Meitu, Momo, Inke, Yinyuetai, Qutoutiao, Xiaoying (VivaVideo), Dewu, and 1,000+ more sites. Full request/response schema: [API Reference](https://platform.snapany.com/docs/api#POST/extract/post). --- # Extract Playlist Source: https://platform.snapany.com/docs/extract-playlist [`POST /openapi/v1/extract/playlist`](https://platform.snapany.com/docs/api#POST/extract/playlist) — 2 credits per page. Extracts one page of posts from a playlist, channel, creator profile or hashtag URL. Use the cursor for pagination: ```bash # First page curl -X POST https://api.snapany.com/openapi/v1/extract/playlist \ -H "Authorization: Bearer sk_snapany_xxx" \ -H "Content-Type: application/json" \ -d '{"url": "https://www.youtube.com/@nasa/videos"}' # Next page: pass the cursor returned by the previous call curl -X POST https://api.snapany.com/openapi/v1/extract/playlist \ -H "Authorization: Bearer sk_snapany_xxx" \ -H "Content-Type: application/json" \ -d '{"url": "https://www.youtube.com/@nasa/videos", "cursor": "..."}' ``` When the response contains no next cursor, you have reached the last page. Each page returns: - **posts**: one page of posts, each **identical in shape** to the Extract Post response — direct media URLs, quality variants, subtitles, stats and author metadata included, no extra per-post calls needed - **profile**: the page subject (channel / creator / hashtag) with display name, avatar, follower count and bio - **has_more / next_cursor**: pagination Full schema and a real-shaped response example: [API Reference](https://platform.snapany.com/docs/api#POST/extract/playlist). ## Supported sites YouTube (channels, playlists, Shorts, hashtags), TikTok (creator profiles, hashtags), Instagram (profiles, hashtags), X/Twitter (creator profiles), Douyin (creator profiles, collections), Bilibili (uploader spaces, collections), Weibo (creator profiles), Toutiao / Xigua Video (creator profiles), Haokan Video (creator profiles), and 50+ more sites. --- # Extract Subtitles Source: https://platform.snapany.com/docs/extract-subtitles [`POST /openapi/v1/extract/subtitles`](https://platform.snapany.com/docs/api#POST/extract/subtitles) — 1 credit per call. Returns video metadata plus **every available subtitle track** (manual and auto-generated, all languages), each with direct download URLs in seven formats: `srt`, `vtt`, `ttml`, `json3`, `srv1`, `srv2`, `srv3`. Currently supports YouTube. ```bash curl -X POST https://api.snapany.com/openapi/v1/extract/subtitles \ -H "Authorization: Bearer sk_snapany_xxx" \ -H "Content-Type: application/json" \ -d '{"url": "https://www.youtube.com/watch?v=jNQXAC9IVRw"}' ``` The response contains: - **id / title / text / duration / published_at / thumbnail_url**: video metadata - **subtitles**: one entry per language track — `language_name` (display name; auto-generated tracks are labeled, e.g. `English (auto-generated)`), `language_tag` (BCP 47 style), and `urls` with a direct download link per format Download the URL of the format you need — `srt`/`vtt` for players and editors, `json3` for programmatic processing with per-cue timestamps. The URLs are signed and expire, so fetch them promptly rather than storing them. A video with no subtitles fails with code `no_subtitles` (HTTP 404) and is **not charged** — catch that code and fall back to [Transcription](https://platform.snapany.com/docs/transcription). Full schema and a real-shaped response example: [API Reference](https://platform.snapany.com/docs/api#POST/extract/subtitles). ## Subtitles vs. Transcription - **This endpoint** returns the subtitles YouTube already has — instant, 1 credit, but only for videos that have them. - **[Transcription](https://platform.snapany.com/docs/transcription)** runs Whisper large-v3 on the audio — works on any video (including those without subtitles) and supports speaker diarization, at 4 credits per minute. A common pipeline: try `/extract/subtitles` first; on a `no_subtitles` error, fall back to [`/transcriptions`](https://platform.snapany.com/docs/transcription). ## Billing 1 credit per successful call, deducted after the extraction succeeds. Failed calls (invalid URL, unsupported site, no subtitles) are never charged. See [Credits & Billing](https://platform.snapany.com/docs/credits). --- # Transcription Source: https://platform.snapany.com/docs/transcription Asynchronous audio/video transcription powered by **Whisper large-v3**, with optional speaker diarization. **Billing**: 4 credits per minute (rounded up), reserved at submission, automatically refunded if the job fails. Endpoints: [`POST /transcriptions`](https://platform.snapany.com/docs/api#POST/transcriptions) [`GET /transcriptions/{id}`](https://platform.snapany.com/docs/api#GET/transcriptions/%7Bid%7D) ## Submit a job Pass a publicly accessible URL (recommended — e.g. a media URL from Extract Post): ```bash curl -X POST https://api.snapany.com/openapi/v1/transcriptions \ -H "Authorization: Bearer sk_snapany_xxx" \ -H "Content-Type: application/json" \ -d '{"fileUrl": "https://example.com/audio.mp3", "speakerLabels": true, "maxSpeakers": 2}' ``` Or upload a local file (max 512MB, max 6 hours): ```bash curl -X POST https://api.snapany.com/openapi/v1/transcriptions \ -H "Authorization: Bearer sk_snapany_xxx" \ -F "file=@meeting.mp3" -F "speakerLabels=true" ``` Response: `{ "id": "...", "status": "processing", "duration": 605.3 }` `language` — an English language name or ISO-639-1 code (e.g. `english`, `en`). **Omit the field to auto-detect; there is no `"auto"` value.** Region subtags like `zh-CN` are rejected with `unsupported_language` — use the base language instead. ## Poll for the result ```bash curl https://api.snapany.com/openapi/v1/transcriptions/{id} \ -H "Authorization: Bearer sk_snapany_xxx" ``` Poll every **3–5 seconds** (polling is free). A polling loop: ```python import time import requests headers = {"Authorization": f"Bearer {API_KEY}"} url = f"https://api.snapany.com/openapi/v1/transcriptions/{job_id}" while True: job = requests.get(url, headers=headers).json() if job["status"] == "completed": print(job["result"]["text"]) break if job["status"] == "failed": # reserved credits are refunded automatically print("failed:", job["error"]) break time.sleep(5) ``` When `status` is `completed`, `result` contains the Whisper verbose_json output: full `text`, detected `language`, and `segments` with start/end timestamps — each segment carries a `speaker` label when diarization is enabled. --- # MCP Source: https://platform.snapany.com/docs/mcp SnapAny ships a hosted **MCP server** (Model Context Protocol, Streamable HTTP). Once it's set up you can just say "extract the video and images from this link" in Claude Code, Codex or Cursor and the agent will call SnapAny — **no code required**. Same API key, same billing as the REST API. **Endpoint**: `https://api.snapany.com/mcp` ## Before you start You need an API key first. Two steps: 1. Create a key under [API Keys](https://platform.snapany.com/console/keys), then **claim 50 free credits** in the [console](https://platform.snapany.com/console) 2. Copy that key — it starts with `sk_snapany_` The `sk_snapany_xxx` in every config below is **a placeholder you must replace with your own real key**. Pasting it as-is won't fail loudly up front, but every call afterwards will. See [Authentication](https://platform.snapany.com/docs/authentication) for key rotation and limits. ## Claude Code ```bash claude mcp add --transport http snapany https://api.snapany.com/mcp \ --header "Authorization: Bearer sk_snapany_xxx" ``` This only applies to **the directory you ran it in**. Add `-s user` to make it available in every project. ## Codex ```toml # ~/.codex/config.toml [mcp_servers.snapany] url = "https://api.snapany.com/mcp" http_headers = { "Authorization" = "Bearer sk_snapany_xxx" } ``` `~` is your home directory; create the file if it doesn't exist. **Restart Codex** afterwards. ## Generic JSON config (Cursor and others) Cursor reads `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` in the project root (that project only). For other clients, check their docs for the MCP config file location. ```json { "mcpServers": { "snapany": { "url": "https://api.snapany.com/mcp", "headers": { "Authorization": "Bearer sk_snapany_xxx" } } } } ``` **Restart the client** afterwards. ## Verify the connection In Claude Code, run: ```bash claude mcp list ``` Seeing `snapany` listed as connected means you're set — `/mcp` inside a session works too. Other clients show the server in their MCP settings panel. **If the six tools below are listed, it's working.** ## Available tools | Tool | What it does | | ------------------- | ----------------------------------------------------- | | `extract_post` | Extract media/metadata from a post URL (1 credit) | | `extract_playlist` | Extract one page of a playlist/channel (2 credits) | | `extract_subtitles` | Extract subtitle tracks with download URLs (1 credit) | | `transcribe` | Submit a transcription job (4 credits/min, reserved) | | `get_transcription` | Poll a transcription result (free) | | `get_docs` | Read these docs from inside your agent (free) | Both extract tools return **direct media links and metadata, not the files themselves**. To actually save something locally, have your agent download the link it got back — most clients can do that directly. ## Credits New developers can claim 50 free credits in the [console](https://platform.snapany.com/console), and credits **never expire**. Your balance and top-ups live there too; per-call usage is under [Credits history](https://platform.snapany.com/console/usage). When you run out, tools return `Insufficient credits`. Full billing rules are in [Credits & Billing](https://platform.snapany.com/docs/credits). ## Troubleshooting | Symptom | Most likely cause | | --------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | Connection failed / 401 | `sk_snapany_xxx` wasn't replaced with a real key, or the `Bearer ` prefix is missing (note the space after `Bearer`) | | Config saved but no tools show up | The client wasn't restarted | | 429 `rate_limited` | Rate limited — the quota is shared with the REST API (1,200 requests/minute) | ## Next steps - [Authentication](https://platform.snapany.com/docs/authentication) — creating and rotating API keys - [Credits & Billing](https://platform.snapany.com/docs/credits) — the billing model and topping up - [API Reference](https://platform.snapany.com/docs/api) — full endpoint docs with a try-it console Try telling your agent: _"Extract this YouTube video and transcribe its audio with speaker labels: https://..."_