Getting Started with the FastSaver API

The FastSaver API is one endpoint that turns a social media link into downloadable media: send a URL, get JSON back with direct file links. It powers fastsaver.io and @fastsaver_bot, and it covers TikTok, Instagram, YouTube, Facebook, X and Pinterest. This guide takes you from zero to a parsed response in three languages, then covers the parts most quickstarts skip: errors and rate limits.

Keys and auth

Get a key at api.fastsaver.io and send it with every request as a header:

X-Api-Key: YOUR_KEY

Two rules. The key belongs on your server — never in a browser bundle or a mobile app, where anyone can lift it from the network tab; proxy through your own backend instead. And treat it like a password: environment variable, not source control.

The call: POST /v1/fetch

One request handles every platform except YouTube (more on that below). It is a POST with a JSON body:

curl -X POST "https://api.fastsaver.io/v1/fetch" \
  -H "X-Api-Key: YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "url": "https://www.tiktok.com/@nba/video/7302394762168954158" }'

JavaScript

const res = await fetch('https://api.fastsaver.io/v1/fetch', {
  method: 'POST',
  headers: {
    'X-Api-Key': process.env.FASTSAVER_KEY,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ url: 'https://www.instagram.com/reel/DRVO0TKkWPD/' })
});

const data = await res.json();
if (!res.ok) throw new Error(data.code + ': ' + data.message);
console.log(data.medias);

Python

import os
import requests

r = requests.post(
    'https://api.fastsaver.io/v1/fetch',
    headers={'X-Api-Key': os.environ['FASTSAVER_KEY']},
    json={'url': 'https://www.instagram.com/reel/DRVO0TKkWPD/'},
    timeout=30,
)
data = r.json()
if r.ok:
    for media in data['medias']:
        print(media['quality'], media['ext'], media['url'])
else:
    print(data['code'], data['message'])

Two optional body fields: audioOnly (true returns just the audio track) and mute (true returns the video without sound). Both default to false.

Reading the response

Every successful fetch returns the same shape, whatever the platform:

{
  "platform": "tiktok",
  "kind": "single",
  "title": "this transition took 3 hours",
  "author": "@user",
  "thumbnail": "https://p16-sign.tiktokcdn-us.com/obj/cover.jpg",
  "duration": 27,
  "medias": [
    { "type": "video", "quality": "auto", "ext": "mp4",
      "url": "https://v16m-default.tiktokcdn.com/a1b2c3/video.mp4", "size": 4831092 },
    { "type": "audio", "quality": "audio", "ext": "mp3",
      "url": "https://sf16-ies-music.tiktokcdn.com/obj/sound.mp3" }
  ]
}

The parts that matter:

  • medias is the list of downloadable files. Each entry has a type (video, audio or image), a display quality, an ext like mp4 or jpg, the download url, and a size in bytes when known. A video post is usually one entry; TikTok adds the sound as a second, audio entry — details in the TikTok API guide.
  • kind tells you what you are rendering. single is one post. album is a carousel: one medias entry per photo or video, each with its own thumbnail — see the Instagram API guide. youtube means the entries are quality variants of one video, not separate files.
  • thumbnail, title, author and duration (seconds) exist for your UI — enough to render a preview card without touching the media files.

YouTube is two steps

A YouTube response (kind: "youtube") lists the available qualities in medias — 1080p down to audio-only, with sizes — but you resolve the one you want with a second call. Keep the sourceUrl field from the response; the download step needs it. Both requests and both responses are shown in the YouTube API guide.

When it fails

Errors are one flat shape, always with a 4xx or 5xx status:

{
  "error": true,
  "code": "unsupported",
  "message": "paste a link from a supported platform"
}

The codes you will see:

  • invalid (400) — malformed body or missing URL. Fix the request.
  • unsupported (422) — the URL parses but is not from a supported platform, or is not a post URL at all. In practice this means an end user pasted a profile link or a search page instead of a post. Surface the message; do not retry — nothing will change.
  • forbidden (403) — missing or wrong key. Check the X-Api-Key header before checking anything else.
  • unreachable — the post is private, deleted, region-locked, or the platform refused to serve it. Occasionally transient: one retry after a few seconds is reasonable, more is wasted.
  • rate_limited (429) — over quota. The retry-after header says how long to wait; respect it.
  • server_error (500) — our side. Retry with backoff, a couple of attempts, then tell the user.

Practical rule: branch on error being present, show message to humans, switch on code in code.

Rate-limit etiquette

  • Successful responses carry an x-ratelimit-remaining header. Read it — throttling yourself before the 429 arrives beats handling the 429.
  • Dedupe. Three users pasting the same viral link inside a minute should be one API call plus a short-lived cache on your side, not three calls.
  • Do not pre-fetch. Resolve media when someone actually asks for it — this matters most on YouTube, where resolving every quality up front burns quota on links nobody clicks.
  • On 429, wait out retry-after. Hammering a rate limiter has never un-rate-limited anyone.

That is the whole surface: one auth header, one endpoint, one success shape, one error shape. Platform-specific details live in their own short guides — TikTok, Instagram, YouTube — and if you are wondering what to ship, here are six things developers build on a media download API. The API overview has it all on one page.

Frequently asked questions

Can I call /v1/fetch directly from browser JavaScript?
No — your API key would be visible to anyone who opens devtools. Call it from your backend and expose your own thin endpoint to the browser.
What does a 422 response mean?
The code is unsupported: the link is not from a supported platform, or is not a post URL — usually a profile or search page. Fix the link; retrying will not help.
Which errors are safe to retry?
server_error with backoff, unreachable once, and rate_limited after the retry-after header expires. Any other 4xx means the request itself is wrong — retrying sends the same wrong request.
How do I pick a file from the medias array?
Filter by type (video, audio or image), then use quality, ext and size to decide or to build a picker. Albums have one entry per item; YouTube entries are quality variants of one video.