Easydown API

API documentation

Use the Easydown API from your backend, scripts, or automation services to parse public media links into a unified response shape.

Production endpoint

POST https://api.easydown.org/api/v1/parse

Authentication

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

Request format

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/..."
}

Supported URL formats

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.

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 links

Profiles, live pages, and TikTok Lite pages are not supported.

Douyin

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 URLs

Profiles, search, collections, follow pages, and live pages are not supported.

YouTube

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.

X / Twitter

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.

Instagram

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.

Xiaohongshu

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 URL

Profiles, search pages, collections, and private notes are not supported.

Bilibili

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.

Kuaishou

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 URL

Profiles, search pages, collections, live pages, and private videos are not supported.

Weibo

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 URL

Profiles, search pages, topics, super topics, live pages, articles, and collections are not supported.

API key permissions

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.

Unified response

{
  "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"
}

Response fields

FieldTypeDescription
platformstringNormalized platform name such as instagram or youtube.
titlestringMedia title or caption when available.
thumbnailstringPreview image URL when available.
durationnumberDuration in seconds. Images and galleries usually return 0.
images[]arrayDownloadable image items with url, width, and height.
videos[]arrayDownloadable video items with url, quality, mimeType, dimensions, hasAudio, and source.
audios[]arrayDownloadable audio items when the platform exposes audio separately.

Media URL download notes

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.

Why direct browser downloads fail

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.

Recommended backend proxy flow

  1. Call Easydown API from your server and store the returned media URL only for short-term use.
  2. When the user downloads, send the request to your own backend proxy with the media URL and platform.
  3. Your backend streams the platform media URL with the recommended headers and forwards the response body to the browser.
  4. Forward Range requests for large videos so players and download managers can resume downloads.
  5. If a media URL expires, call the parse API again and retry with the refreshed URL.

General rules

  • Browser-side fetch or download may fail because many media CDNs block cross-origin requests.
  • For stable downloads, fetch media from your backend and set a browser User-Agent plus the platform Referer when needed.
  • Use streaming or Range requests for large files instead of loading the entire file into memory.
  • Media URLs may expire. If a URL stops working, call the parse API again to refresh it.
  • Private, deleted, region-restricted, live, DRM-protected, or copyright-restricted content may not be downloadable.

Platform header requirements

PlatformRecommended headersCookie needed?Special handlingExpiration notes
DouyinReferer: https://www.douyin.com/; browser User-Agent; forward Range when present.Usually noUse server-side streaming for video and image-note media.URLs are short lived. Re-parse when a link returns 403 or 404.
TikTokReferer: https://www.tiktok.com/; browser User-Agent.SometimesSome 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.
BilibiliReferer: https://www.bilibili.com/; browser User-Agent; forward Range.For some high-quality or account-limited streamsDASH results can return separate video and audio URLs. Download both and merge with FFmpeg.Re-parse when signed stream URLs expire.
XiaohongshuReferer: https://www.xiaohongshu.com/; browser User-Agent.SometimesImage and video CDNs can enforce strict anti-hotlinking. Download through your backend.Re-parse when the CDN URL becomes invalid.
WeiboReferer: https://weibo.com/ or https://m.weibo.cn/; browser User-Agent.Usually noChoose the quality URL that matches your product needs when multiple URLs are returned.Image and video URLs can expire. Re-parse to refresh.
YouTubeReferer: https://www.youtube.com/; Origin: https://www.youtube.com; browser User-Agent.For protected or age/account-limited contentHigh-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.
InstagramReferer: https://www.instagram.com/; browser User-Agent.SometimesBrowser preview can hit CORS or CORP. Use backend proxy downloads for stable delivery.CDN URLs may expire. Re-parse public posts when needed.
KuaishouReferer: https://www.kuaishou.com/; browser User-Agent; forward Range.Usually noUse server-side streaming for large short-video files.Media URLs can expire. Re-parse the public video link.
X / TwitterReferer: https://x.com/; browser User-Agent.Usually noVideo media may include multiple bitrates. Select the quality that fits your use case.Re-parse when selected media variants fail.

Backend streaming examples

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.mp4

Troubleshooting

  • 403 usually means missing Referer, missing User-Agent, expired URL, required Cookie, or region restriction.
  • 404 often means the media URL expired. Re-parse the original post URL.
  • CORS or CORP errors usually mean the browser should not request the platform CDN directly. Use your backend proxy.
  • Empty or partial files usually mean Range or streaming was not forwarded correctly.

Supported platforms

TikTokDouyinYouTubeX / TwitterInstagramXiaohongshuBilibiliKuaishouWeibo

Billing behavior

A successful parse costs 1 credit. Failed parses, unsupported links, authentication failures, and platform response failures do not charge credits.

Supported content

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.

Common errors

HTTPCodeMeaning
401missing_token / invalid_tokenAuthorization header is missing or the token is invalid.
401token_expiredThe API token has passed its expiration date. Edit the key or create a new one.
403platform_not_allowedThe API token is not allowed to access the platform detected from the URL.
402insufficient_creditsThe account does not have enough credits for a successful parse.
400302The URL format is unsupported or not a single supported media post.
200304Easydown could not return downloadable media for this public link.

Need integration help? Join Telegram or Discord support.