On this page
Quickstart
This documentation covers the current version (v1) of the API. If you are still using the legacy, unversioned API (/openapi/…), its documentation is on GitHub at Media-Downloader-API, and the migration guide is Migrating from the legacy API.
v1 is the current version of the developer API. Every endpoint lives under https://api.meowload.net/openapi/v1, and authentication is a single Authorization: Bearer <your API key> header. The full list of endpoints, parameters and response schemas is in the API reference. This page only gets your first request working.
Get an API key
Go to the Developer Console to get your API key. It is an opaque string. Treat it like a password: never ship it in frontend code or commit it to a public repository.
Every <your API key> in the examples below is a placeholder that you must replace with your own key.
Your first request
Extracting a single post:
curl -X POST https://api.meowload.net/openapi/v1/extract/post \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <your API key>" \
-H "Accept-Language: en" \
-d '{"url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"}'What the three headers do:
| Header | Required | Description |
|---|---|---|
Content-Type | Yes | Always application/json |
Authorization | Yes | Bearer <your API key>, with one space between Bearer and the key |
Accept-Language | No | Language of error messages. Defaults to en; zh, ja, es, de and more are supported. |
Read the response
A successful call returns HTTP 200, and the body is the extraction result itself:
{
"site": "youtube",
"id": "dQw4w9WgXcQ",
"title": "Rick Astley - Never Gonna Give You Up (Official Video)",
"text": "The official video for “Never Gonna Give You Up” by Rick Astley.",
"medias": [
{
"media_type": "video",
"resource_url": "https://rr3---sn-example.googlevideo.com/videoplayback?expire=1757300000&id=o-AbC",
"preview_url": "https://i.ytimg.com/vi/dQw4w9WgXcQ/maxresdefault.jpg",
"duration": 213,
"variants": [
{
"quality": 1080,
"quality_label": "1080p",
"video_url": "https://rr3---sn-example.googlevideo.com/videoplayback?itag=137&expire=1757300000",
"video_ext": "mp4",
"video_filesize": 58203122,
"audio_url": "https://rr3---sn-example.googlevideo.com/videoplayback?itag=140&expire=1757300000",
"audio_ext": "m4a",
"audio_filesize": 3451212,
"is_default": true
},
{
"quality": 720,
"quality_label": "720p",
"video_url": "https://rr3---sn-example.googlevideo.com/videoplayback?itag=22&expire=1757300000",
"video_ext": "mp4",
"video_filesize": 31776500
}
]
}
],
"author": {
"username": "RickAstleyVEVO",
"display_name": "Rick Astley",
"avatar_url": "https://yt3.ggpht.com/example=s176-c-k-c0x00ffffff-no-rj"
},
"stats": {
"view_count": 1600000000,
"like_count": 18000000
},
"created_at": "2009-10-25T06:57:33Z",
"post_url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ"
}A few things to keep in mind:
- Both
titleandtextare optional. Sites with titles (YouTube, Bilibili, Xiaohongshu, Reddit, and so on) may return both; sites without titles (Twitter, Instagram, Douyin, TikTok, and so on) only returntext. For a display caption, usetitle || text. - Missing values are omitted entirely, never sent as
nullor an empty string. Read every optional field with a fallback. medias[].variants[]lists the resolutions or audio tracks of one media item.qualityis the height in pixels (9999means original quality) andquality_labelis the display label. When there are several variants, the one withis_default: trueis the recommended pick. A variant that has bothvideo_urlandaudio_urlis a split stream: download both and merge them.- Media URLs are short-lived. Download promptly; do not store them or embed them in a page.
- When a media item carries
headers, send those headers as-is when downloading, or the platform will reject the request. siteis the platform id the link belongs to (for exampleyoutubeortiktok). It is omitted when the link cannot be classified.
The response shapes for profile batch extraction (/extract/playlist) and subtitles (/extract/subtitles) are in the API reference.
Handle failures
Every non-200 response has the same body shape:
{
"message": "The content has been deleted or does not exist",
"code": "content_deleted",
"retryable": false
}messageis human-readable and localized byAccept-Language. Do not branch on it.codeis the machine-readable error code. Every400carries one, and429is alwaystoo_many_requests.retryabletells you whether retrying the same URL later might succeed.
Branch on the status code:
| Status | Meaning | What to do |
|---|---|---|
400 | Extraction failed | Read code and retryable: true means retry after a delay, false is final, use another URL |
401 | Invalid API key | Check that the Authorization header is Bearer <your API key> |
402 | Out of credits | Top up in the Developer Console |
422 | Invalid request body | For example a missing url or non-JSON body; detail lists the validation issues |
429 | Rate limited | 1,200 requests per minute per key; code is too_many_requests; back off and retry |
500 | Server error | Retry later; contact us if it persists |
Extraction failures (400) are not charged. All 18 error codes are listed in Errors.
Billing and credits
Only 200 responses are charged. The amount depends on the endpoint and the platform; the rules are listed under "Billing rules" in the Developer Console. Checking your credits is free.
Check your remaining credits at any time:
curl https://api.meowload.net/openapi/v1/credits \
-H "Authorization: Bearer <your API key>"{ "availableCredits": 282539 }We send email and SMS alerts when your balance drops below 10,000, 2,000, 300, 100 and 0. You can also build your own monitoring on this endpoint.
Next steps
- API reference: full definitions of the four endpoints, with a try-it console
- POST /extract/post for a single post
- POST /extract/playlist for profiles and playlists
- POST /extract/subtitles for subtitles
- GET /credits for remaining credits
- Migrating from the legacy API: field rename tables from the legacy API to v1
- Errors: the 18 extraction error codes and what
retryablemeans - MCP: call the API from Claude Code, Codex or Cursor
- Code examples: Python, JavaScript, PHP, Golang