Skip to main content

fastsaver — Instagram, TikTok and YouTube downloader API for Python (FastSaverAPI SDK)

One Python API to download Instagram reels and posts, TikTok videos without watermark, YouTube as MP4 (up to 4K) or MP3, plus Pinterest, Facebook, X/Twitter, RuTube and Likee. Includes a Shazam song-recognition API and YouTube audio delivered as a Telegram file_id for music bots. Sync and async. Free tier: 1,000 credits, no credit card.

PyPI Python versions License: MIT CI Checked with mypy Free 1,000 credits Telegram

from fastsaver import FastSaver

client = FastSaver("fs_sk_...")  # or export FASTSAVER_API_KEY
video = client.fetch("https://www.tiktok.com/@scout2015/video/6718335390845095173")
print(video.download_url)        # direct MP4 link, no watermark

Start free: 1,000 credits, no credit card; paid plans from $9/month for 100,000 credits. Create a key at api.fastsaver.io/auth (email, Google or Telegram login), pip install fastsaver, and you are downloading in under a minute.

Sign up · API docs · Pricing · Telegram community · support@fastsaver.io


Table of contents

Why FastSaverAPI

Scraping social networks yourself means proxies, cookies, IP bans, captchas and a parser that breaks every time Instagram or TikTok ships an update. FastSaverAPI is a hosted social media downloader API: you send a link, you get back direct download URLs and metadata in one stable JSON shape. No browser automation, no yt-dlp upgrades at 3 a.m., no servers to babysit.

  • Free to start — 1,000 credits on sign-up, no credit card, 10 requests/minute.
  • 8 platforms, one endpoint — Instagram, TikTok, Pinterest, Facebook, X/Twitter, RuTube, Likee via client.fetch(url), plus a full YouTube toolset. Every result has the same fields.
  • TikTok without watermark, Instagram reels/carousels/stories, YouTube up to 2160p (4K) and MP3/audio.
  • Built for Telegram bots — turn a YouTube video into a Telegram file_id in one call, backed by a cache of millions of tracks. Your bot never downloads or uploads a byte.
  • Shazam built in — recognise a song from a voice message, browse charts, fetch lyrics.
  • Predictable billing — a fixed credit price per call; a failed resolve costs 0.1 credit; bad key, no credits or rate-limit rejections cost nothing.
  • Fast — Instagram and TikTok fetches typically answer in under a second; popular posts come straight from cache.

Why this SDK

  • Sync and async clients with identical method names: FastSaver / AsyncFastSaver.
  • Typed, frozen dataclasses for every response — the full JSON is always on .raw.
  • Precise exceptions: AuthenticationError, InsufficientCreditsError, RateLimitError, NotFoundError, FetchError, and InvalidArgumentError for mistakes caught before a request.
  • Automatic retries with exponential backoff for network errors, 5xx and 429.
  • Streaming save() that writes any download link to disk without leaking your API key.
  • A fastsaver command-line tool for quick checks and shell scripts.
  • Zero heavy dependencies — just httpx. Python 3.9+. Fully type-hinted (py.typed), checked with mypy --strict.
  • 800+ mocked test cases (respx) run in CI on Python 3.9 through 3.14 — uv run pytest needs no API key.

FastSaverAPI vs yt-dlp, instaloader and DIY scrapers

yt-dlp, instaloader and friends are great tools. They run on your machine, which is the whole difference:

Self-hosted scrapers (yt-dlp, instaloader, custom) FastSaverAPI + fastsaver
Keeps working when platforms change You update, redeploy, and hope Handled server-side, same JSON
Proxies, cookies, IP bans, captchas Your problem, your cost Included
TikTok without watermark Depends on the current extractor Yes
YouTube 4K + MP3 conversion Needs ffmpeg and CPU on your server Done upstream, you get a link
Telegram delivery Download → upload to Telegram (≤ 50 MB) file_id in one call, no upload
Song recognition (Shazam) Separate service Built in
Time to first working call Hours to days Minutes — 1,000 free credits
Marginal cost per link $0 (plus servers, proxies, your time) From ~$0.14 per 1,000 links on Pro
Works offline / no third party Yes No — it is a hosted API
Cost model Servers, proxies, maintenance time From $0; Pro at $9 / 100,000 credits

When yt-dlp is still the right tool: one-off personal downloads, archiving your own channel at zero marginal cost, or environments that must not call an external service. FastSaverAPI is for apps and bots that need to keep working every day without you maintaining scrapers.

Supported platforms, credit costs and plans

Platform What you can download Credits / request
Instagram Posts, reels, IGTV, carousels (albums) 1.5
Instagram Stories and highlights 5
TikTok Videos without watermark, photo posts, the original sound 1.5
YouTube Video info and available formats 2
YouTube Music search (YouTube Music) 2
YouTube Download MP4 144p–1080p, or audio/MP3 15
YouTube Download 1440p (2K) / 2160p (4K) 25
YouTube → Telegram Audio as a Telegram file_id 7 (cached) · 15 (first time)
Pinterest Pins, videos, idea pins (pinterest.com, pin.it) 1.5
Facebook Videos and reels (facebook.com, fb.com, fb.watch) 1.5
X / Twitter Videos, GIFs and images (x.com, twitter.com) 1.5
RuTube Videos (rutube.ru, rutube.com) 3
Likee Videos (likee.video, likee.com) 3
Shazam Identify a song from audio 5
Shazam Top charts by country 1
Shazam Lyrics by title and artist 2
Account Balance and plan free

Credits are consumed per successful call. Paid plans start at $9/month. Rate limits are per API key in a fixed 60-second window, shared across /fetch, /youtube/* and /shazam/*.

Plan Price / month Credits / month Requests / min What that buys
Free $0 — no card 1,000 10 ~660 Instagram/TikTok fetches, or ~66 YouTube downloads, or ~140 cached Telegram tracks
Pro $9 100,000 60 ~66,000 fetches, or ~6,600 YouTube downloads, or ~14,000 cached Telegram tracks
Ultra $39 500,000 250 ~333,000 fetches, or ~33,000 YouTube downloads
Mega $99 1,500,000 900 ~1,000,000 fetches, or ~100,000 YouTube downloads

On Pro that works out to roughly $0.14 per 1,000 Instagram/TikTok links, $1.35 per 1,000 YouTube MP4/MP3 downloads and $0.63 per 1,000 cached Telegram audio tracks (Ultra and Mega are cheaper per credit). A failed resolve (private, deleted, unsupported URL) costs 0.1 credit; rejected requests (bad key, no credits, rate limit) cost nothing. Pay by card or crypto. Current prices and plan details: https://api.fastsaver.io/pricing.

Install

pip install fastsaver
uv add fastsaver

Requires Python 3.9 or newer. The only dependency is httpx.

Get your API key

  1. Sign up at api.fastsaver.io/auth — email code, Google or Telegram login. No card needed for the Free plan.
  2. Copy your key from the dashboard. It looks like fs_sk_....
  3. Export it so FastSaver(), AsyncFastSaver() and the CLI find it automatically:
export FASTSAVER_API_KEY="fs_sk_..."          # macOS / Linux
$env:FASTSAVER_API_KEY = "fs_sk_..."          # Windows PowerShell

Or pass it explicitly: FastSaver(api_key="fs_sk_..."). Without a key the client raises ConfigurationError at construction time, before any request.

Quickstart (sync)

from fastsaver import FastSaver

with FastSaver() as client:  # reads FASTSAVER_API_KEY
    result = client.fetch("https://www.instagram.com/p/DRsmm9UjKfH/")

    print(result.source)      # instagram.com
    print(result.type)        # image | video | album
    print(result.caption)

    if result.is_album:
        # Carousels have no top-level download_url — iterate the items
        for item in result.items:
            print(item.type, item.download_url, item.width, item.height)
    else:
        print(result.download_url, result.width, result.height, result.duration)

    # Every download link, regardless of type
    for url in result.download_urls:
        print(url)

    print(result.raw)         # the JSON exactly as the API returned it

Save a result to disk — save() streams the file, follows redirects and never sends your API key to the file host. Keep it inside the same with block (a closed client raises ConfigurationError):

from fastsaver import FastSaver

with FastSaver() as client:
    result = client.fetch("https://www.instagram.com/p/DRsmm9UjKfH/")

    if result.is_album:
        # Carousels have no top-level download_url — save every item
        for i, url in enumerate(result.download_urls, 1):
            client.save(url, f"downloads/{result.id}_{i}")
    elif result.download_url:
        # Pick your own file name ...
        path = client.save(result.download_url, f"downloads/{result.id}.mp4")

        # ... or hand it a directory (created on demand) and let the response name the file
        path = client.save(result.download_url, "downloads/")
        print(path)

The remaining sections assume one open client created for the whole program:

from fastsaver import FastSaver

client = FastSaver()  # reads FASTSAVER_API_KEY; call client.close() at exit

Ready to run this? Get a free API key — 1,000 credits (about 660 Instagram/TikTok fetches), no card.

Async client and bulk downloads

AsyncFastSaver has the same endpoint methods — just await them (close it with await client.aclose() or async with). Reuse one instance per application; it is safe to use from many coroutines at once.

import asyncio
from fastsaver import AsyncFastSaver, FastSaverError

URLS = [
    "https://www.instagram.com/reel/DRsmm9UjKfH/",
    "https://www.tiktok.com/@scout2015/video/6718335390845095173",
    "https://pin.it/4nUh8Jx",
]

REQUESTS_PER_MINUTE = 10   # Free plan; Pro 60, Ultra 250, Mega 900 (see client.balance().rpm_limit)

async def main() -> None:
    # Rate limits are counted per API key in a FIXED 60-second window and the API sends no
    # Retry-After, so space requests out client-side instead of firing everything at once.
    # A semaphore alone only limits concurrency, not requests per minute.
    gap = 60 / REQUESTS_PER_MINUTE
    lock = asyncio.Lock()

    async with AsyncFastSaver() as client:

        async def fetch(url: str):
            async with lock:            # one request every `gap` seconds
                await asyncio.sleep(gap)
            return await client.fetch(url)

        results = await asyncio.gather(*(fetch(u) for u in URLS), return_exceptions=True)
        for url, r in zip(URLS, results):
            if isinstance(r, FastSaverError):
                print("failed:", url, r)
            else:
                print(r.source, r.type, r.download_urls)
                for link in r.download_urls:
                    await client.save(link, "downloads/")

asyncio.run(main())

await client.save(url, dest) works the same way as the sync version (the network part is async; disk writes are ordinary blocking writes). Downloads from the CDN do not count against the API rate limit — only fetch, youtube.* and shazam.* calls do.

Instagram downloader API (reels, posts, stories)

An Instagram reels downloader in Python is one call: client.fetch() handles reels, posts, carousels, IGTV, stories and highlights. Every post form works: instagram.com/p/…, /reel/…, /tv/…, /share/… links and /stories/<user>/<story_id>/.

reel = client.fetch("https://www.instagram.com/reel/DRsmm9UjKfH/")
print(reel.type, reel.download_url, reel.thumbnail_url, reel.duration)

post = client.fetch("https://www.instagram.com/p/C1abcDEfGhI/")
if post.is_album:
    # carousel: one file per slide (items carry their own type/size)
    for i, item in enumerate(post.items, 1):
        if item.download_url:
            ext = "mp4" if item.is_video else "jpg"
            client.save(item.download_url, f"downloads/{post.id}_{i}.{ext}")
elif post.download_url:
    client.save(post.download_url, "downloads/")   # single image or video, named by the response

story = client.fetch("https://www.instagram.com/stories/nasa/3141592653589793238/")  # 5 credits

Notes: a private or deleted post raises NotFoundError / FetchError (0.1 credit). Profile URLs are rejected — pass a post, reel or story link.

TikTok downloader API (no watermark)

A TikTok video downloader API without watermark: videos come back clean, no watermark, photo posts as albums, and every result carries the original sound:

tt = client.fetch("https://www.tiktok.com/@scout2015/video/6718335390845095173")
print(tt.download_url)           # clean MP4, no watermark
print(tt.width, tt.height, tt.duration, tt.caption)

if tt.music:
    print(tt.music.title, tt.music.author, tt.music.download_url)   # MP3 of the sound

Short vm.tiktok.com/… and vt.tiktok.com/… links are accepted too.

YouTube to MP4 and MP3 download API (up to 4K)

# Download a YouTube video in Python without yt-dlp or ffmpeg: metadata + available formats.
# Accepts watch, youtu.be, shorts, embed, live URLs or a bare id.
info = client.youtube.info("https://www.youtube.com/watch?v=HanBb8FonWs")
print(info.title, info.author, info.duration)   # duration in seconds
print(info.available_formats)    # ['audio', '144p', '360p', '720p', '1080p', ...]
print(info.best_video_format)    # '1080p'
for f in info.formats:
    print(f.type, f.format, f.filesize)

# YouTube Music search: 10 results per page, pages 1-3
search = client.youtube.search("the weeknd one of the girls", page=1)
for track in search:
    # track.duration is a "m:ss" string; use track.duration_seconds for an int
    print(track.video_id, track.title, track.duration, track.url)

# Download as MP4 ("144p" ... "2160p") ...
dl = client.youtube.download("https://youtu.be/HanBb8FonWs", format="720p")   # 15 credits
print(dl.filename, dl.download_url)

# ... or as audio/MP3 ("audio" — "mp3"/"m4a" are aliases)
mp3 = client.youtube.download("https://youtu.be/HanBb8FonWs", format="audio")  # 15 credits

# The link is valid for 10 minutes — save it right away
if dl.download_url:
    path = client.save(dl.download_url, "downloads/")   # file name comes from the response
    print(path)
  • download_url needs no API key and redirects to the actual file. It expires after 10 minutes (it can be reused until then); an expired link raises DownloadError from save().
  • An invalid format raises InvalidArgumentError before any credits are spent.
  • Conversion happens upstream, so a download can take a while — the SDK uses a 120 s read timeout for this call. Override per call with timeout=.

Telegram music bot: YouTube audio as a file_id

The killer feature for a Telegram music bot in Python. audio_for_bot returns a Telegram file_id for the audio of a YouTube video, so your bot calls send_audio without downloading, converting or uploading anything — no 50 MB upload limit, no bandwidth, no ffmpeg. Millions of tracks are pre-cached: a cache hit costs 7 credits and returns in seconds; a miss is downloaded first (15 credits, may take a minute or more — the default read timeout for this call is 300 s).

audio = client.youtube.audio_for_bot("vk6014HuxcE", "@my_music_bot")
print(audio.file_id)

# Prefer the channel/message pair? (for copy_message-style delivery)
ref = client.youtube.audio_for_bot("vk6014HuxcE", "@my_music_bot", return_file_id=False)
print(ref.channel_id, ref.message_id)

A file_id is bot-scoped: it only works for the bot you pass as bot_username (the leading @ is added for you). Store the file_id — re-sending it later is a plain Telegram call that costs no credits.

Minimal aiogram 3 handler (pip install "aiogram>=3"). BOT_USERNAME must be the username of the bot whose token you pass to Bot(...) — a file_id only works for that bot:

import os

from aiogram import Bot, Dispatcher, types
from aiogram.filters import Command

from fastsaver import AsyncFastSaver, FastSaverError

BOT_TOKEN = os.environ["BOT_TOKEN"]          # from @BotFather
BOT_USERNAME = os.environ["BOT_USERNAME"]    # "@my_music_bot" — the SAME bot as BOT_TOKEN

bot = Bot(BOT_TOKEN)
dp = Dispatcher()
saver = AsyncFastSaver()  # reads FASTSAVER_API_KEY

@dp.message(Command("song"))
async def song(message: types.Message) -> None:
    query = (message.text or "").partition(" ")[2].strip()
    if not query:
        await message.answer("Usage: /song <title or artist>")
        return
    try:
        search = await saver.youtube.search(query)              # 2 credits
        track = next((t for t in search if t.video_id), None)
        if track is None or track.video_id is None:
            await message.answer("Nothing found.")
            return
        audio = await saver.youtube.audio_for_bot(track.video_id, BOT_USERNAME)  # 7 / 15 credits
    except FastSaverError as exc:
        await message.answer(f"Could not fetch audio: {exc}")
        return
    if audio.file_id is None:
        await message.answer("No file_id returned for this track.")
        return
    await message.answer_audio(audio.file_id, title=track.title)  # no download, no upload

dp.run_polling(bot)

A complete bot lives in examples/telegram_bot_aiogram.py.

Building a Telegram music bot? The Free plan's 1,000 credits cover ~140 cached tracks — enough to ship a prototype today: api.fastsaver.io/auth. Pro ($9) covers ~14,000 cached tracks a month.

Pinterest, Facebook, X/Twitter, RuTube and Likee video downloader

The same client.fetch(url) call is a Pinterest video downloader, Facebook reels downloader and X/Twitter video downloader API, and returns the same MediaResult:

pin = client.fetch("https://pin.it/4nUh8Jx")                          # Pinterest (pin.it / pinterest.com)
fb  = client.fetch("https://fb.watch/abc123/")                        # Facebook video / reel
x   = client.fetch("https://x.com/NASA/status/1727080000000000000")   # X / Twitter video, GIF, images
ru  = client.fetch("https://rutube.ru/video/0123456789abcdef/")       # RuTube (3 credits)
lk  = client.fetch("https://l.likee.video/v/AbCdEf")                  # Likee share link (3 credits)

for r in (pin, fb, x, ru, lk):
    print(r.platform, r.type, r.download_urls)

Not sure which platform a link belongs to? detect_platform(url) mirrors the server's routing and returns "youtube" for links you should send to client.youtube.*, None for unsupported hosts, and "instagram_story" for story links:

from fastsaver import CREDIT_COSTS, detect_platform

platform = detect_platform("https://vm.tiktok.com/ZMabc/")   # 'tiktok'

if platform is None:
    print("unsupported URL (would cost 0.1 credit if sent)")
elif platform == "youtube":
    print("use client.youtube.info / download / audio_for_bot")
else:
    print(CREDIT_COSTS[platform])   # 1.5 — the /fetch platforms are keys of CREDIT_COSTS

Shazam API for Python: identify songs, top charts, lyrics

# Song recognition API in Python: identify a song from a clip (mp3/m4a/ogg/mp4, up to 50 MB;
# 5-15 s of clear audio is enough)
match = client.shazam.identify("clip.ogg")
print(match.title, "-", match.artist, match.thumbnail)
if match.best_match:
    print("YouTube:", match.best_match.url)   # ready for youtube.download / audio_for_bot

# Top charts: a country code ("us", "gb", "de", ...) or "world"; 10 tracks per page, pages 1-3
for track in client.shazam.top(country="world", page=1):
    print(track.title, track.duration, track.url)

# Lyrics by title + artist (exactly as identify() returned them)
print(client.shazam.lyrics("Blinding Lights", "The Weeknd"))

Recognise a Telegram voice message (in-memory buffers need a filename= so the recogniser knows the container — Telegram voice notes are OGG/Opus). A complete aiogram 3 handler, using the same bot, dp, saver and BOT_USERNAME as the music-bot example above:

from aiogram import F, types
from fastsaver import FastSaverError

@dp.message(F.voice)
async def recognise(message: types.Message) -> None:
    assert message.voice is not None            # guaranteed by the F.voice filter
    buf = await bot.download(message.voice)     # aiogram: BytesIO
    if buf is None:
        await message.answer("Could not download the voice note.")
        return
    try:
        match = await saver.shazam.identify(buf, filename="voice.ogg")   # 5 credits
    except FastSaverError as exc:
        await message.answer(f"Recognition failed: {exc}")
        return
    if not match.title:
        await message.answer("No match.")
        return
    await message.answer(f"{match.title}{match.artist}")
    # Deliver the song itself: best YouTube match -> Telegram file_id
    if match.best_match and match.best_match.video_id:
        audio = await saver.youtube.audio_for_bot(match.best_match.video_id, BOT_USERNAME)
        if audio.file_id:
            await message.answer_audio(audio.file_id, title=match.title, performer=match.artist)

file may be a path, bytes, an open binary file, or a (filename, data[, content_type]) tuple.

Balance and usage

balance() is free and has its own limit of 60 requests per minute.

b = client.balance()
print(b.plan, b.credits, "/", b.plan_credits)   # Free 987 / 1000
print(b.rpm_limit, b.balance, b.auto_renew)     # 10 0.00 False   (balance is a Decimal, USD)
print(b.plan_expires_at, b.expire_label)        # 2026-10-09 12:00:00+00:00 Ends in 30 days
print(b.is_free_plan)                            # True

Error handling

A call either returns a model (ok: true) or raises a subclass of FastSaverError — you never inspect HTTP status codes. Bad arguments (empty URL, unknown format, oversized file) raise InvalidArgumentError before any request is made; it is both a FastSaverError and a ValueError.

from fastsaver import (
    FastSaver,
    FastSaverError,
    AuthenticationError,
    InsufficientCreditsError,
    RateLimitError,
    NotFoundError,
    FetchError,
)

client = FastSaver()

try:
    result = client.fetch("https://www.instagram.com/p/DRsmm9UjKfH/")
except AuthenticationError:
    print("Invalid API key — check FASTSAVER_API_KEY")
except InsufficientCreditsError:
    print("Out of credits — top up at https://api.fastsaver.io/dashboard")
except RateLimitError:
    # Fixed 60-second window per key and no Retry-After header: wait for the window to roll over
    print("Rate limited — wait up to 60 s (Free: 10 requests/min), then retry")
except NotFoundError:
    print("Post not found (private, deleted or wrong URL)")
except FetchError as exc:
    print("Resolve failed:", exc.code)        # fetch.failed, fetch.timeout, "fetch.error: 502", ...
except FastSaverError as exc:
    print("Something else went wrong:", exc)  # bad argument, network, timeout, 5xx, validation
else:
    print(result.download_urls)
FastSaverError
├── ConfigurationError            missing API key, closed client
├── InvalidArgumentError          bad argument, caught client-side (also a ValueError)
├── APIError                      any non-2xx (.status_code, .detail, .body)
│   ├── AuthenticationError       401
│   ├── InsufficientCreditsError  400 "Insufficient credits" — there is no HTTP 402
│   ├── RateLimitError            429 (.retry_after when the server sends Retry-After)
│   ├── InvalidRequestError       400 bad URL / format / bot username / file too large
│   │   └── ValidationError       422 (.errors)
│   ├── FetchError                400 resolve failed (.code, .upstream_status)
│   │   └── NotFoundError         code "not.found"
│   └── ServerError               5xx
├── TransportError                connection problems (wraps httpx errors)
│   └── RequestTimeoutError
└── DownloadError                 save(): final response was not 2xx (e.g. expired link)

Billing notes:

  • Requests rejected by a guard — bad key, no credits, rate limit, bad format, bad bot username, oversized file — cost nothing.
  • A resolve that reaches the platform and fails (FetchError, NotFoundError, and an unsupported host on fetch()) costs 0.1 credit.
  • Running out of credits is reported as HTTP 400 with InsufficientCreditsError, not 402.

Retries, timeouts, proxies

import httpx
from fastsaver import FastSaver

client = FastSaver(
    max_retries=3,                              # default 2
    timeout=httpx.Timeout(30.0, connect=5.0),   # default Timeout(60.0, connect=10.0)
)

# Per-call override for slow operations
dl = client.youtube.download("https://youtu.be/HanBb8FonWs", format="2160p", timeout=300)
  • Retried automatically with exponential backoff and jitter: connection errors, HTTP 5xx and HTTP 429 (429 backs off 2 s, 4 s; a Retry-After header is honoured, capped at 30 s).
  • Not retried: read timeouts — the server may already have done (and billed) the work. You get a RequestTimeoutError immediately and decide yourself.
  • Default read timeouts: 60 s for most calls, 120 s for youtube.download, 300 s for youtube.audio_for_bot and save(). The per-call timeout= always wins.
  • Rate limits are a fixed 60-second window per key and the API sends no Retry-After, so for bulk jobs space requests out client-side (see the async example) rather than relying on retries.

Bring your own httpx client for proxies, custom transports or HTTP/2. The SDK does not close it, always applies its own timeouts, and never follows redirects on API calls (so your key is never replayed to another host).

import httpx
from fastsaver import FastSaver, AsyncFastSaver

http = httpx.Client(proxy="http://user:pass@proxy.example:8080")
client = FastSaver(http_client=http)

ahttp = httpx.AsyncClient(http2=True)     # needs: pip install "httpx[http2]"
aclient = AsyncFastSaver(http_client=ahttp)

FastSaver is thread-safe — create one instance and share it. AsyncFastSaver belongs to the event loop it was created in.

Command-line interface

The package installs a fastsaver command (also python -m fastsaver). Output is the raw API response as indented JSON; pass --compact for single-line JSON in pipelines.

export FASTSAVER_API_KEY="fs_sk_..."

fastsaver fetch "https://www.instagram.com/reel/DRsmm9UjKfH/"
fastsaver youtube info "https://youtu.be/HanBb8FonWs"
fastsaver youtube search "the weeknd" --page 2
fastsaver youtube download "https://youtu.be/HanBb8FonWs" --format 1080p --out ./downloads/
fastsaver youtube tg-audio vk6014HuxcE --bot @my_music_bot [--no-file-id]
fastsaver shazam identify clip.ogg
fastsaver shazam top --country us --page 1
fastsaver shazam lyrics "Blinding Lights" "The Weeknd"
fastsaver balance
fastsaver save "https://api.fastsaver.io/v1/tunnel?id=..." ./downloads/

Global options: --api-key, --base-url, --timeout, --compact, --version. Errors go to stderr with exit code 1 (2 for usage errors), so the CLI is safe in scripts:

fastsaver --compact fetch "$URL" | jq -r '.download_url // .items[].download_url'

Constants for your own accounting:

from fastsaver import CREDIT_COSTS, YOUTUBE_FORMATS, detect_platform, extract_youtube_id

CREDIT_COSTS["youtube_download"]                   # 15
YOUTUBE_FORMATS                                    # ('audio', '144p', ..., '2160p')
detect_platform("https://vm.tiktok.com/ZMabc/")    # 'tiktok'
extract_youtube_id("https://youtu.be/HanBb8FonWs") # 'HanBb8FonWs'

FAQ

How do I download an Instagram reel or post with Python? client.fetch("https://www.instagram.com/reel/…") returns download_url (video/image) or items for carousels; client.save(url, "downloads/") writes it to disk. Stories and highlights use the same call.

How do I download TikTok videos without a watermark in Python? client.fetch(tiktok_url).download_url is the clean MP4. Photo posts come back as an album, and result.music.download_url is the original sound.

How do I get a YouTube video as MP4 or MP3 without yt-dlp? client.youtube.download(url, format="1080p") (or format="audio" for MP3/M4A) returns a link valid for 10 minutes; save it with client.save(). Formats go up to 2160p (4K).

How do I send YouTube music in a Telegram bot without downloading it? client.youtube.audio_for_bot(video_id, "@your_bot") returns a Telegram file_id; pass it to send_audio / answer_audio. 7 credits when cached, 15 the first time anyone asks.

How do I recognise a song from a Telegram voice message? await saver.shazam.identify(buf, filename="voice.ogg") — 5 credits — returns title, artist, cover art, lyrics and matching YouTube tracks you can deliver with audio_for_bot.

Is it really free? Yes: every account gets 1,000 credits without a card (about 660 TikTok/Instagram fetches, 66 YouTube downloads, or ~140 cached Telegram audio tracks) at 10 requests/minute. Paid plans start at $9/month for 100,000 credits.

Do I need Instagram cookies, a login, or proxies? No. You send a public post URL and an API key; sessions, proxies and captchas are handled on FastSaverAPI's side. Nothing runs in a browser on your machine.

Can it download from private Instagram accounts or a whole profile? No. Only public posts, reels, stories and highlights are supported, one URL per call; profile URLs are rejected. A private or deleted post raises NotFoundError / FetchError (0.1 credit).

Can I use it in a commercial app or a public Telegram bot? The SDK is MIT-licensed. Use of the API itself is governed by the FastSaverAPI terms at https://api.fastsaver.io; paid plans (Pro/Ultra/Mega) are designed for production bots and apps, with rate limits from 60 to 900 requests per minute.

I don't use Python — is there a REST API for Node.js, PHP or Go? Yes. This package is a thin client over the plain HTTPS/JSON API documented at https://api.fastsaver.io/docs; every call here maps to one endpoint (GET /v1/fetch, POST /v1/youtube/download, POST /v1/youtube/audio/tg-bot, POST /v1/shazam/identify, …) with an X-Api-Key header.

Which URLs are supported? Instagram (instagram.com), TikTok (tiktok.com, vm.tiktok.com), YouTube (youtube.com, youtu.be, shorts, music), Pinterest (pinterest.com, pin.it), Facebook (facebook.com, fb.com, fb.watch), X/Twitter (x.com, twitter.com), RuTube (rutube.ru, rutube.com), Likee (likee.video, likee.com). detect_platform(url) tells you before you spend a credit.

Does the SDK work with asyncio, FastAPI, aiogram, python-telegram-bot? Yes — AsyncFastSaver is a normal httpx-based async client. Create one instance at startup and reuse it.

Is my API key safe? The key is sent only to api.fastsaver.io over HTTPS. save() downloads from CDNs without the key, API calls never follow redirects, and the key is masked in repr() and never logged.

What happens when a post is private or deleted? You get NotFoundError or FetchError (with .code) and 0.1 credit is charged for the attempt. Retrying will not help; guard rejections (bad key, rate limit, no credits) are free.

Examples

All examples read FASTSAVER_API_KEY from the environment and live in examples/:

  • quickstart.py — fetch any supported URL and print its download links.
  • async_batch.py — download many URLs concurrently, paced to your plan's rate limit, with per-URL error reporting.
  • youtube_download.py — pick a format from youtube.info, download, save to disk.
  • telegram_bot_aiogram.py — a complete music bot: search → file_idanswer_audio.
  • shazam_identify.py — identify a local clip, print the best YouTube match and lyrics.

Support, contributing, license

Not signed up yet? Create a free key — 1,000 credits, no card, and pricing from $9/month when you outgrow it.

If this SDK saves you an afternoon, a ⭐ on GitHub helps other developers find it.

Pull requests are welcome — see CONTRIBUTING.md. Tests are fully mocked with respx (800+ test cases, Python 3.9–3.14 in CI), so uv sync && uv run pytest needs no API key. Security issues: see SECURITY.md.

The SDK is released under the MIT License. Use of the FastSaverAPI service is subject to its own terms at https://api.fastsaver.io.


Русский — Python SDK для FastSaverAPI

Скачивание видео и фото из Instagram, TikTok (без водяного знака), YouTube (MP4 до 4K и MP3), Pinterest, Facebook, X/Twitter, RuTube и Likee через один API, распознавание музыки (Shazam) и аудио из YouTube как Telegram file_id для ботов. Sync и async клиенты. 1 000 кредитов бесплатно, без карты: https://api.fastsaver.io/auth. Поддержка в Telegram: https://t.me/fastsaverapi.

O'zbekcha — FastSaverAPI uchun Python SDK

Instagram, TikTok (suv belgisiz), YouTube (4K gacha MP4 va MP3), Pinterest, Facebook, X/Twitter, RuTube va Likee'dan video/rasm yuklab olish, Shazam orqali musiqani aniqlash va Telegram botlar uchun YouTube audioni file_id ko'rinishida olish — bitta API. Sync va async. 1 000 kredit bepul, karta shart emas: https://api.fastsaver.io/auth. Telegram: https://t.me/fastsaverapi.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastsaver-0.1.0.tar.gz (103.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastsaver-0.1.0-py3-none-any.whl (51.9 kB view details)

Uploaded Python 3

File details

Details for the file fastsaver-0.1.0.tar.gz.

File metadata

  • Download URL: fastsaver-0.1.0.tar.gz
  • Upload date:
  • Size: 103.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fastsaver-0.1.0.tar.gz
Algorithm Hash digest
SHA256 f0e4f68a9b1410b0ff7e814a65163e9fdd5db0603c0debaaeb6b8b39401aa3e1
MD5 7efb8d247c18001ae0bafec9ca5523d9
BLAKE2b-256 6f6c8f09a789883aeda4dc238b4425bde58f678bd7769853a4a8aa7be6ad02d9

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastsaver-0.1.0.tar.gz:

Publisher: publish.yml on coder2077/fastsaver

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file fastsaver-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: fastsaver-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 51.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for fastsaver-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 46dfb4fa5d1aef66238d84dc8c81cf866c410fe2d1b03f2b2707aefdf0162bba
MD5 8e21064b7032c2f4687c74f9761f32cd
BLAKE2b-256 80f1dbc2e609e7e4959a0e29ead2cb215ae70e81e3ccfed1f09972fdcd65e0c7

See more details on using hashes here.

Provenance

The following attestation bundles were made for fastsaver-0.1.0-py3-none-any.whl:

Publisher: publish.yml on coder2077/fastsaver

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page