Media API

Send a public post URL. Receive source media URLs and metadata. Download directly, stream through the API, or request a temporary server copy.

OpenAPI 3.1 specification ยท Import this URL into your API client.

Authentication

Use Authorization: Bearer YOUR_API_KEY. Local setup writes your key to tmp/media-api/api-key and a private curl configuration to tmp/media-api/client.curl.

Resolve a post

curl --config tmp/media-api/client.curl \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://www.youtube.com/shorts/YIT2Up1imWs","quality":"720"}' \
  http://127.0.0.1:8098/v1/resolve
FieldValues
urlHTTPS link to a specific supported public media post
mediaall (default), video, audio
qualitybest or a short-edge pixel limit from 144 to 4320
proxy_modeauto (default), direct for ordinary egress, or proxy for a configured paid route

Results contain ordered items and their formats, with URLs, dimensions, codecs, sizes and safe public headers. Use recommended_format_ids for checked source representations. Separate video/audio streams require client-side merging; HLS/DASH require a suitable downloader. Source cookies and authorization headers are not disclosed.

Source links can expire or depend on IP and headers. expires_at: null means unknown; refresh_after is a cache hint. Cross-network usability must be verified before commercial launch.

There is no 1080p cap: request best or an explicit ceiling up to 4320p. Only available source renditions are returned; the API does not transcode a smaller version.

Streaming fallback

After a failed direct download, send POST /v1/tunnels with the original operation_id, item_index and format_id. The API returns a relative url and expires_at. Both SDKs expose tunnel() and return an absolute URL. GET the ticket URL without an API key; keep that URL private.

{"operation_id":"OPERATION_ID","item_index":0,"format_id":"FORMAT_ID"}

There is no repeated extraction or second resolution unit. Original file bytes stream through the server without storage, conversion or merging. Progressive HTTP(S) files only; HLS/DASH and separate-track merging remain client responsibilities. A tunnel cannot repair an unavailable source or missing login.

Tickets expire within five minutes of resolution and allow three GETs. Limits: 256 MiB and ten minutes per transfer, 1 GiB per client/UTC day, and daily transfer attempts up to three times the resolution quota. Single byte ranges depend on source support. Disconnect cancels upstream. Restarts invalidate tickets.

Automatic delivery and temporary storage

Send POST /v1/deliveries with the same selection, mode: "auto", and failed_modes: []. The response selects a direct link first, a tunnel after a reported direct failure, then temporary storage after both methods fail. Explicit modes are direct, tunnel and stored.

The SDK detects transfer errors and reports them. Python download() and Node downloadTo() perform this sequence automatically. A ready stored copy can be reused after a direct failure without fetching the source again. The server cannot observe a client's independent CDN download or a normal browser download button.

POST /v1/files explicitly stores an owned resolved format. It responds immediately with 202 and a status URL. Poll GET /v1/files/{id}; a ready response includes a download URL, actual size, SHA-256 and expiry. DELETE /v1/files/{id} cancels or deletes it. Repeated requests reuse an active or ready copy.

Only complete original files are published. Defaults: 256 MiB per file, 1 GiB total disk, 15-minute retention, ten GETs per file and two simultaneous transfers. Stored downloads support byte ranges. Source fetches and downloads share the daily traffic budget with tunnels; no extra resolution unit is charged. Expiry, cancellation and restart remove bytes. Storage is never started merely by resolving a URL.

Public-data scraping

The same local API key can run independent scraping operations. GET /v1/scrapers lists registered source/operation pairs and current runtime features. Registration does not guarantee that a source accepts requests from this machine. Use the live catalog rather than a hardcoded site list.

curl --config tmp/media-api/client.curl \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: app-search-example-1' \
  -d '{"source":"apple","operation":"search","query":"notes","limit":5}' \
  http://127.0.0.1:8098/v1/scrape

Requests accept source, operation, and operation-specific url, query, id, username, country, language, page, limit, headers and options. Responses contain request_id, operation_id, result, cache_hit and usage. The independent result includes source, operation, fetch time and a data object; screenshots expose genuine bytes in data.image_base64. Use /v1/resolve for downloadable media formats.

Successful scraping operations share the existing rate, daily usage and concurrency budgets. Matching idempotent scraping responses remain in bounded memory for up to 60 seconds. Only a request fingerprint is persisted; source parameters, private headers and source bodies are not stored in operation records. Python exposes scrapers() and scrape(source, operation, **options); Node exposes scrapers() and scrape(source, operation, options).

Fetch targets, redirects and browser network requests must pass public HTTP(S) destination validation. Private, loopback, link-local and metadata addresses are rejected. Browser rendering requires its local runtime; real geographic or residential routing requires a matching configured proxy. A browser is not a CAPTCHA solver. Missing integrations return dependency_missing; observed source challenges, login requirements and rate limits return structured errors. Optional error.requires identifies a needed dependency. Paid proxy and CAPTCHA credentials are not provisioned.

Optional adaptive proxy routing

Scraper requests select options.proxy_mode; media resolution selects top-level proxy_mode. auto starts with ordinary egress, through Squid in Compose, and permits one paid retry for eligible source blocks, challenges, rate limits without source backoff, or transport timeouts. A successful retry may create a ten-minute route preference. Ordinary success clears it; paid failure clears it and starts a one-minute cooldown. Login requirements, private/missing content, parse failures, explicit source backoff and cancellation do not trigger a paid retry. Automatic retries do not move configured account sessions or sensitive customer headers to a paid route.

direct uses ordinary egress. proxy requires an enabled matching operator paid pool and may use configured source authentication. Provider credentials and endpoints are operator-only. With no paid pool there is no paid traffic. The API and browser keep their existing isolated networks; paid providers are reached through Squid with exact endpoint CONNECT exceptions, public target validation and IP pinning.

Default shared paid caps: 20 attempts and 128 MiB per UTC day globally, 10 attempts and 64 MiB per client/day, 32 MiB per operation, and one paid grant per source operation. Grants last at most one minute. Limits include HTTP, browser, native extraction and enabled media delivery; metered transport bytes include protocol overhead. Limits and route preferences are held in bounded memory and reset on restart. Private --adaptive-proxy-config settings can change these limits or disable paid routing.

Scraper result.routing contains mode (direct/proxy), attempts and provider_bytes; media routing uses route (free/proxy). Formats marked delivery_requires_proxy may depend on the provider's IP. Paid media streaming and storage require explicit private allow_paid_media: true; by default they return paid_media_disabled before fetching the source. Clients may try returned source URLs from their own connection. Provider refusals and allowance limits return safe codes without revealing provider details. See docs/scraper-api.md for private configuration and restrictions.

Asynchronous scraping

POST /v1/scrape/jobs accepts {"request":{...}} and optional callback_url/callback_secret. Poll the returned status_url with the owning API key or cancel with DELETE. The queue retains at most 64 jobs and 16 MiB of completed results for up to 15 minutes; completed results can expire earlier under memory pressure. Jobs do not survive restart. An optional Idempotency-Key replays a retained owned job with matching request and callback settings. A successful job's result contains the synchronous scrape envelope.

Optional callbacks POST the job ID, status and result/error to a validated public HTTP(S) URL. A nonempty separate secret adds X-Scraper-Signature: sha256=..., an HMAC-SHA256 over the exact JSON body bytes. Empty secrets leave callbacks unsigned. Delivery makes up to three bounded attempts; a delivery failure does not rerun the source. Localhost callbacks are rejected; local clients can poll instead. SDK helpers: Python create_scrape_job(), scrape_job(), cancel_scrape_job(); Node createScrapeJob(), scrapeJob(), cancelScrapeJob().

The repository guide docs/scraper-api.md documents selectors, errors and callback verification. Reference coverage in docs/scraper-catalog.json is a checklist, not a claim of full provider parity or successful live access.

Media platforms

YouTube, Instagram, TikTok, X/Twitter, Facebook and Pinterest. Pinterest accepts individual image/video pins, regional pin URLs and pin.it short links. Playlists, boards, profiles and VK Video are excluded from media resolution.

TikTok photo posts retain their images and separate soundtrack. Instagram photo-post music is returned when the source exposes its audio URL. Instagram supports individual live Stories, current /stories/USER/ collections and saved /stories/highlights/ID/ collections, up to 100 ordered photos/videos. Optional story_media_id selects one item. These routes require a separate API session and a confirmed public owner; missing authorization returns 403 authentication_required. Session setup is described in docs/media-api.md.

Endpoints

EndpointPurpose
POST /v1/resolveResolve source media links
POST /v1/deliveriesSelect direct, tunnel or stored delivery
POST /v1/tunnelsCreate a streaming fallback for an owned result
GET /v1/tunnels/{token}Stream the selected source file
POST /v1/filesRequest a temporary source copy
GET /v1/files/{id}Own file status and download capability
DELETE /v1/files/{id}Cancel or delete own file
GET /v1/downloads/{token}Download original stored bytes or a range
GET /v1/scrapersRegistered source operations and runtime features
POST /v1/scrapeRun a public-data operation
POST /v1/scrape/jobsCreate an asynchronous scraping job
GET /v1/scrape/jobs/{id}Read an owned job and callback status
DELETE /v1/scrape/jobs/{id}Cancel an owned job
GET /v1/usageOwn media, scraping, transfer and storage usage
GET /healthzLocal service readiness

Usage and retries

Successful resolutions consume one usage unit. Failures consume none. In-flight requests reserve a unit. An optional Idempotency-Key prevents duplicate processing/accounting. Matching requests reuse the operation for 24 hours; the original result remains in bounded memory for at most one minute. An expired result returns 409 result_expired; use a new key to resolve again. Errors contain a code, message, retry hint and request ID. Usage units do not trigger payments.

Local setup

Default: two simultaneous source operations, a 45-second deadline, 60 resolution requests per minute per client and a bounded metadata cache. Runtime data and keys are isolated from Telegram. Python/JavaScript clients and server-sizing notes are in examples/media-api and docs/media-api.md.

General web tools

Use source: web with an available operation. Access depends on the target website and runtime features.

binary, extract, images, links, markdown, post, scrape, screenshot, sessions, universal_search

Scraping sources and operations

Registered operations may depend on source availability. Use the live catalog to check runtime features.

Amazon

autocomplete
Public amazon autocomplete data
bestsellers
Public amazon bestsellers data
offers
Public amazon offers data
product
Public amazon product data
reviews
Public amazon reviews data
Public amazon search data

App Store

product
Public App Store product
reviews
Public App Store reviews
Public App Store search

Bing

images
Extract public bing images results.
Extract public bing search results.
shopping
Extract public bing shopping results.

Brave Search

Extract public brave search results.

DuckDuckGo

Extract public duckduckgo search results.

Facebook

posts
Public facebook posts data
profile
Public facebook profile data

Flipkart

product
Public flipkart product data
Public flipkart search data

Google

ads_transparency
Google ads transparency
ai_mode
Google ai mode
ai_overview
Google ai overview
autocomplete
Extract public google autocomplete results.
finance
Google finance
flights
Google flights
hotels
Google hotels
images
Extract public google images results.
immersive_product
Google immersive product
Extract public google light_search results.
local
Extract public google local results.
maps_photos
Google maps photos
maps_places
Google maps places
maps_posts
Google maps posts
maps_reviews
Google maps reviews
Google maps search
news
Google news
Google news search
news_v2
Google news v2
patent_details
Google patent details
Google patents search
scholar_author
Google scholar author
scholar_author_citations
Google scholar author citations
scholar_cite
Google scholar cite
Google scholar search
shopping
Extract public google shopping results.
shorts
Extract public google shorts results.
Google trends
Google trends autocomplete
Google trends trending now
videos
Extract public google videos results.

Google Play

apps
Public Google Play apps
books
Public Google Play books
category
Public Google Play category
games
Public Google Play games
product
Public Google Play product
reviews
Public Google Play reviews
Public Google Play search

Indeed

jobs
Public indeed jobs data

Instagram

posts
Public instagram posts data
profile
Public instagram profile data

LinkedIn

company
Public linkedin company data
job
Public linkedin job data
jobs
Public linkedin jobs data
post
Public linkedin post data
profile
Public linkedin profile data

Myntra

product
Public myntra product data
Public myntra search data

Swiggy Instamart

listing
Public swiggy listing data
product
Public swiggy product data
Public swiggy search data

TikTok

ads
Public tiktok ads data
post
Public tiktok post data
profile
Public tiktok profile data

Walmart

autocomplete
Public walmart autocomplete data
product
Public walmart product data
reviews
Public walmart reviews data
Public walmart search data

X (Twitter)

post
Public x post data
profile
Public x profile data

Yahoo

images
Extract public yahoo images results.
Extract public yahoo search results.

YouTube

channel
Public youtube channel data
comments
Public youtube comments data
Public youtube search data
transcripts
Public youtube transcripts data
video
Public youtube video data

Zillow

property
Public zillow property data
Public zillow search data