Errors
All errors share one JSON shape:
{ "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 |
| 402 | insufficient_credits | Balance too low | Top up in the 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, or not supported by this endpoint | Check which sites the endpoint accepts, or contact us to request the site |
no_subtitles | The video has no subtitle tracks (HTTP 404) | Fall back to 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,timeoutandunknownare 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 returningextract_failed, orunknownshows up repeatedly, contact us with the request time.
age_restricted,region_restrictedandlive_stream_not_supportedonly 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.
403 Forbidden when downloading YouTube media
This 403 does not come from the SnapAny API: extraction succeeded, but downloading the returned YouTube video_url / audio_url / resource_url from your own server fails. YouTube often refuses downloads from data-center IPs (cloud servers, VPS), and some links only download from US IPs — sending the media headers doesn't change that.
Use YouTube Proxy Download instead: it returns the same response plus proxy URLs for variants up to 1080p, which download through our network rather than from YouTube directly. If a proxy URL returns 404 (payload_expired), call the endpoint again; a 403 (upstream_error) is rare and a single retry usually succeeds, but call the endpoint again if it persists.
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.