TikTok
Supports public single videos and photo posts.
tiktok.com/@user/video/{id}tiktok.com/@user/photo/{id}tiktok.com/t/{shortCode}vm.tiktok.com/{code} or other TikTok share linksProfiles, live pages, and TikTok Lite pages are not supported.
Easydown API
Use the Easydown API from your backend, scripts, or automation services to parse public media links into a unified response shape.
POST https://api.easydown.org/api/v1/parse
Send your private API token as a Bearer token. Do not embed ed_live tokens in browser JavaScript.
Authorization
Bearer ed_live_xxx
Content-Type
application/json
curl -X POST https://api.easydown.org/api/v1/parse \
-H "Authorization: Bearer ed_live_xxx" \
-H "Content-Type: application/json" \
-d '{"url":"https://www.instagram.com/reel/..."}'{
"url": "https://www.instagram.com/reel/..."
}All platforms use the same parse endpoint. The formats below are recognized as public single-media links; final results still depend on whether the content is public and available.
Supports public single videos and photo posts.
tiktok.com/@user/video/{id}tiktok.com/@user/photo/{id}tiktok.com/t/{shortCode}vm.tiktok.com/{code} or other TikTok share linksProfiles, live pages, and TikTok Lite pages are not supported.
Supports public videos, image notes, share links, and selected Douyin CDN media URLs.
v.douyin.com/{code}douyin.com/video/{id}douyin.com/share/video/{id}douyin.com/note/{id}douyin.com/share/note/{id}douyin.com/shipin/{id}douyin.com/vsdetail/{id}douyinpic.com / douyinvod.com / douyinstatic.com media URLsProfiles, search, collections, follow pages, and live pages are not supported.
Supports public single video, Shorts, and live replay URLs that resolve to a video id.
youtu.be/{id}youtube.com/watch?v={id}youtube.com/shorts/{id}youtube.com/live/{id}Playlists, channels, community posts, and private videos are not supported.
Supports public post URLs with a status id.
x.com/{user}/status/{id}twitter.com/{user}/status/{id}Profiles, search pages, spaces, and direct media CDN URLs are not treated as posts.
Supports public posts, Reels, videos, photos, carousels, embeds, and share redirects.
instagram.com/p/{code}instagram.com/reel/{code}instagram.com/reels/{code}instagram.com/tv/{code}instagram.com/{username}/p/{code}instagram.com/{username}/reel/{code}instagram.com/p/{code}/embedinstagram.com/r/{code}instagram.com/share/...Stories, Highlights, profiles, direct messages, Explore pages, and private content are not supported.
Supports public notes, including video and image note links.
xhslink.com/{code}xiaohongshu.com/explore/{noteId}xiaohongshu.com/discovery/item/{noteId}Share text containing a Xiaohongshu URLProfiles, search pages, collections, and private notes are not supported.
Supports public video pages, short links, list pages with bvid, and selected playable pages.
bilibili.com/video/BV...bilibili.com/video/av...b23.tv/{code}bili.im/{code}bilibili.com/list/...?...bvid=BV...bilibili.com/bangumi/play/ep...bilibili.com/bangumi/play/ss...bilibili.com/cheese/play/ss...Watchlater lists, favorites, profile pages, and list pages without a single video id are not supported.
Supports public single Kuaishou video links and share text.
kuaishou.com/short-video/{photoId}kuaishou.com/f/{token}v.kuaishou.com/{token}gifshow.com/fw/photo/{photoId}chenzhongtech.com/fw/photo/{photoId}Share text containing a Kuaishou URLProfiles, search pages, collections, live pages, and private videos are not supported.
Supports public Weibo posts with videos, images, or image galleries.
weibo.com/{uid}/{postId}weibo.com/{uid}/{mblogid}m.weibo.cn/status/{id}weibo.com/tv/show/1034:{id}video.weibo.com/show?fid=1034:{id}t.cn/{code}mapp.api.weibo.cn/fx/...Share text containing a Weibo URLProfiles, search pages, topics, super topics, live pages, articles, and collections are not supported.
API keys can be permanent or expire on a selected date. Leave the expiration blank for a permanent key. You can also limit a key to specific platforms; All platforms means every supported platform is allowed. Editing a key changes its name, expiration, and platform permissions without changing the token value. Reset rotates the token value while keeping its permissions.
{
"status": 200,
"data": {
"platform": "instagram",
"title": "Example title",
"thumbnail": "https://...",
"duration": 12,
"images": [
{
"url": "https://...",
"width": 1080,
"height": 1350
}
],
"videos": [
{
"url": "https://...",
"quality": "HD",
"mimeType": "video/mp4",
"width": 1080,
"height": 1920,
"hasAudio": true,
"source": "direct"
}
],
"audios": []
},
"msg": "success"
}{
"status": 401,
"data": null,
"msg": "Unauthorized",
"code": "missing_token"
}| Field | Type | Description |
|---|---|---|
| platform | string | Normalized platform name such as instagram or youtube. |
| title | string | Media title or caption when available. |
| thumbnail | string | Preview image URL when available. |
| duration | number | Duration in seconds. Images and galleries usually return 0. |
| images[] | array | Downloadable image items with url, width, and height. |
| videos[] | array | Downloadable video items with url, quality, mimeType, dimensions, hasAudio, and source. |
| audios[] | array | Downloadable audio items when the platform exposes audio separately. |
Easydown returns media URLs in images[], videos[], and audios[]. These URLs belong to the original platform and can be affected by expiration, anti-hotlinking, CORS, cookies, region limits, or split audio/video streams.
Many platform CDNs check Origin, Referer, cookies, IP region, and request headers. A URL that works in a server request may fail in browser JavaScript with CORS, CORP, 403, 404, or an empty file.
| Platform | Recommended headers | Cookie needed? | Special handling | Expiration notes |
|---|---|---|---|---|
| Douyin | Referer: https://www.douyin.com/; browser User-Agent; forward Range when present. | Usually no | Use server-side streaming for video and image-note media. | URLs are short lived. Re-parse when a link returns 403 or 404. |
| TikTok | Referer: https://www.tiktok.com/; browser User-Agent. | Sometimes | Some web media requires a valid access cookie such as tt_chain_token from your own browsing context. Region-restricted links may require an accessible server region. | Re-parse and retry when direct access fails. |
| Bilibili | Referer: https://www.bilibili.com/; browser User-Agent; forward Range. | For some high-quality or account-limited streams | DASH results can return separate video and audio URLs. Download both and merge with FFmpeg. | Re-parse when signed stream URLs expire. |
| Xiaohongshu | Referer: https://www.xiaohongshu.com/; browser User-Agent. | Sometimes | Image and video CDNs can enforce strict anti-hotlinking. Download through your backend. | Re-parse when the CDN URL becomes invalid. |
| Referer: https://weibo.com/ or https://m.weibo.cn/; browser User-Agent. | Usually no | Choose the quality URL that matches your product needs when multiple URLs are returned. | Image and video URLs can expire. Re-parse to refresh. | |
| YouTube | Referer: https://www.youtube.com/; Origin: https://www.youtube.com; browser User-Agent. | For protected or age/account-limited content | High-quality streams are often split into audio and video. Merge separated streams with FFmpeg. | Some streams are bound to region or IP. Use an accessible server region and re-parse when needed. |
| Referer: https://www.instagram.com/; browser User-Agent. | Sometimes | Browser preview can hit CORS or CORP. Use backend proxy downloads for stable delivery. | CDN URLs may expire. Re-parse public posts when needed. | |
| Kuaishou | Referer: https://www.kuaishou.com/; browser User-Agent; forward Range. | Usually no | Use server-side streaming for large short-video files. | Media URLs can expire. Re-parse the public video link. |
| X / Twitter | Referer: https://x.com/; browser User-Agent. | Usually no | Video media may include multiple bitrates. Select the quality that fits your use case. | Re-parse when selected media variants fail. |
Node.js / Next.js proxy route
// app/api/media-proxy/route.js
const PLATFORM_HEADERS = {
douyin: {
Referer: 'https://www.douyin.com/',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
tiktok: {
Referer: 'https://www.tiktok.com/',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
bilibili: {
Referer: 'https://www.bilibili.com/',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
xiaohongshu: {
Referer: 'https://www.xiaohongshu.com/',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
weibo: {
Referer: 'https://weibo.com/',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
youtube: {
Referer: 'https://www.youtube.com/',
Origin: 'https://www.youtube.com',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
instagram: {
Referer: 'https://www.instagram.com/',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
kuaishou: {
Referer: 'https://www.kuaishou.com/',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
twitter: {
Referer: 'https://x.com/',
'User-Agent': 'Mozilla/5.0 AppleWebKit/537.36 Chrome/120 Safari/537.36',
},
};
export async function GET(request) {
const { searchParams } = new URL(request.url);
const mediaUrl = searchParams.get('url');
const platform = searchParams.get('platform');
if (!mediaUrl || !platform || !PLATFORM_HEADERS[platform]) {
return Response.json({ error: 'invalid_request' }, { status: 400 });
}
const range = request.headers.get('range');
const headers = { ...PLATFORM_HEADERS[platform] };
if (range) headers.Range = range;
const mediaResponse = await fetch(mediaUrl, { headers });
if (!mediaResponse.ok || !mediaResponse.body) {
return Response.json(
{ error: 'download_failed', status: mediaResponse.status },
{ status: 502 }
);
}
const responseHeaders = new Headers();
const contentType = mediaResponse.headers.get('content-type');
const contentLength = mediaResponse.headers.get('content-length');
const contentRange = mediaResponse.headers.get('content-range');
if (contentType) responseHeaders.set('Content-Type', contentType);
if (contentLength) responseHeaders.set('Content-Length', contentLength);
if (contentRange) responseHeaders.set('Content-Range', contentRange);
responseHeaders.set('Accept-Ranges', 'bytes');
responseHeaders.set('Cache-Control', 'private, max-age=300');
return new Response(mediaResponse.body, {
status: mediaResponse.status,
headers: responseHeaders,
});
}Browser usage
// Browser code: call your own backend, not the platform CDN directly.
const downloadUrl = new URL('/api/media-proxy', window.location.origin);
downloadUrl.searchParams.set('platform', media.platform);
downloadUrl.searchParams.set('url', media.videos[0].url);
window.location.href = downloadUrl.toString();Merging separated audio and video
# When video and audio are returned separately, download both files first.
ffmpeg -i video.mp4 -i audio.m4a -c copy output.mp4A successful parse costs 1 credit. Failed parses, unsupported links, authentication failures, and platform response failures do not charge credits.
The API is built for public single-post media. Private posts, deleted content, region-limited media, live streams, profiles, search pages, and collection pages are not supported.
| HTTP | Code | Meaning |
|---|---|---|
| 401 | missing_token / invalid_token | Authorization header is missing or the token is invalid. |
| 401 | token_expired | The API token has passed its expiration date. Edit the key or create a new one. |
| 403 | platform_not_allowed | The API token is not allowed to access the platform detected from the URL. |
| 402 | insufficient_credits | The account does not have enough credits for a successful parse. |
| 400 | 302 | The URL format is unsupported or not a single supported media post. |
| 200 | 304 | Easydown could not return downloadable media for this public link. |
Need integration help? Join Telegram or Discord support.