Every crawl is a task. This page is the full reference for submitting, polling, and reading one, plus the response schema and error codes.

Submit a task

string
required
The platform, e.g. youtube, tiktok, douyin, weibo, bilibili. See /v1/task-sources for the full list.
string
required
What to do: search, posts, user, detail, comments, hot, recommended, trending, download. Not every platform supports every action.
object
required
Action parameters. The common fields:
202 Accepted
Write verbs (publishing) are irreversible: they return 409 needs_confirmation until you re-send with confirm: true, run a single attempt (never auto-retried), and accept an idempotency_key so a timed-out retry never double-posts.

Poll a task

Returns the task’s status; a succeeded task also carries result — the Envelope.

Retry & cancel

Re-run a finished task.
Cancel a queued or running task and release its per-account slot — useful when you’ve stopped waiting on the tail of a fan-out. Both forms do the same thing.

The Envelope

The normalized response every read returns.
boolean
true for a successful crawl (including an honest empty result); false when error is set.
string
Provenance: live (freshly crawled), cache (served from a recent crawl), empty (a real, no-results answer), or blocked (the platform served a bot-check / risk control). empty and blocked are different answers — render them differently.
integer
The number of items.
Item[]
The normalized cards — see Item.
string
Pass back as params.cursor for the next page.
integer
For a cache source: how old the cached result is, in seconds.
integer
How long the crawl took.
object
Set only when ok is false{ code, message, retryable }. See Errors.

The Item

One normalized card — the stable consumer projection. It never ranks or scores; stats are the platform’s own raw numbers.
string
Globally unique and stable: "douyin:7412…".
string
video | image | text.
string
The platform, e.g. youtube.
string
The caption / body.
string
Display name.
string
The platform’s creator id (sec_uid, uid, …).
string
The @handle.
string
Canonical profile URL, derived centrally.
string
The post’s canonical URL.
string
A torii-hosted cover URL (/v1/media?u=…).
ItemMedia[]
{ kind: "video"|"image", url, w, h, duration_s }. URLs are torii-hosted, never a raw CDN URL. A playable stream appears on detail; the flat search/posts harvest is metadata-only for some platforms.
object
On video items — { url, w, h, seconds, status }, a low-res, muted, full-length (≤240s) scrubbable clip. See Media & previews.
integer
Created-at, unix seconds.
number
Video length in seconds (omitted when unknown).
object
{ width, height } of the media.
object
{ likes, comments, shares, views } — verbatim.
string
Per-item origin (live / cache).

Sample responses

A finished task is polled with GET /v1/tasks/{id}; the shape of its result depends on what the action returns, not the platform. There are five return shapes. Each block below is the result value (the poll wrapper { "task_id", "status": "succeeded", "result": … } is omitted for brevity).
detail re-resolves a single ref to a full Item including a playable media[].url (and, on video, a preview). Use it when the flat search/posts harvest was metadata-only.
result — douyin.detail
comments returns its own shape: a flat list of normalized Comments plus a total and has_more (page with params.cursor). Note it carries source, not the envelope’s ok.
result — weibo.comments
user returns a creator, not cards — identity + profile-level stats land in data.author (items is empty). A field the platform doesn’t expose comes back 0/absent — read a 0 as “not reported”, not a hard fact.
result — douyin.user

emptyblocked (the honesty contract)

A no-results answer and a bot-check are different, and both are succeeded tasks — branch on source, never on an empty items.
empty — a real, honest
blocked — a captcha / risk control (retryable; do NOT prompt re-login)

Write verbs

A publish/delete returns a WriteResultstate is the outcome; a dry_run returns state: "planned" without posting. Send idempotency_key so a timed-out retry replays instead of double-posting.
result — weibo.comment.create (confirm:true)
state is one of planned (dry-run) · published · deleted · session_expired · blocked · rejected · duplicate. A duplicate means an in-flight retry of the same idempotency_key — poll the original.

Errors

When ok is false, error.code is machine-readable. Branch on it — never parse the message.
blocked and session_expired are deliberately distinct. A blocked task is a transient challenge — retry it. Only session_expired (surfaced on /v1/profiles) means the account needs a human re-login.