Threads Public Video Resolver API + Comments

Threads Public Video, Comments + Search API

Resolve public Threads video metadata, export available comments, and search public posts or profiles.

Quickstart in 60 seconds

  1. Get a beta API key from /beta or ask an admin to create one.
  2. Send a public Threads post URL to POST /v1/threads/video.
  3. Choose video download_mode, call POST /v1/threads/comments for replies, or use POST /v1/threads/search.
curl -X POST https://api.clipmagic.ru/v1/threads/video \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"url":"https://www.threads.net/@example/post/example","download_mode":"proxy","include_metadata":true,"include_thumbnail":true}'

Endpoint: Search Threads

POST /v1/threads/search returns a normalized bounded public window. It supports ranked posts, recent posts, and profiles.

FieldTypeRequiredDescription
querystring 1–256yesSearch phrase; whitespace is normalized.
search_typetop | recent | profilesnoResult family; default top.
limitinteger 1–50noMaximum returned records; default 20.
curl -X POST https://api.clipmagic.ru/v1/threads/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: YOUR_API_KEY" \
  -d '{"query":"OpenAI","search_type":"profiles","limit":10}'
Search has no continuation cursor because the logged-out public source does not expose a reliable one. The response reports only window.limit and window.returned.

Endpoint: Export Threads Comments

POST /v1/threads/comments returns a flat oldest-first page containing top-level and nested public replies. Use parent_id and root_post_id to reconstruct the tree.

FieldTypeRequiredDescription
urlstringyesPublic Threads post URL.
limitinteger 1–100noPage size; default 50.
cursorstring | nullnoOpaque signed cursor from the preceding page, for the same URL and limit.
let cursor = null;
do {
  const response = await fetch("https://api.clipmagic.ru/v1/threads/comments", {
    method: "POST",
    headers: { "Content-Type": "application/json", "X-API-Key": process.env.THREADS_API_KEY },
    body: JSON.stringify({ url: "https://www.threads.com/@example/post/example", limit: 50, cursor })
  });
  const page = await response.json();
  if (!response.ok) throw new Error(page.error.message);
  console.log(page.comments);
  cursor = page.retrieval.status === "paginated" ? page.pagination.next_cursor : null;
  if (page.retrieval.status === "partial") console.warn("Public provider returned a partial conversation");
} while (cursor);

A traversal stays pinned to its first provider. Public Relay uses the current refetch cursor when available; the logged-out browser capability can continue through a deterministic public window; configured authorized providers forward only their own upstream cursor.

partial means the selected public provider cannot expose more replies. It is not a complete snapshot guarantee.

Authentication

Use the X-API-Key header on resolve requests. Full API keys are shown once at creation and are stored server-side only as HMAC hashes.

Only public or authorized content is supported. Login, CAPTCHA, DRM, private content and anti-bot bypass are not supported. Authorized user cookies are not used.

Endpoint: Resolve Threads Video

POST /v1/threads/video accepts a Threads post URL and returns post metadata plus video media variants when available.

FieldTypeRequiredDescription
urlstringyesPublic Threads post URL.
download_modeurl | metadata_only | proxynoControls whether direct URLs, metadata only, or temporary proxy links are returned.
include_metadatabooleannoInclude post metadata fields.
include_thumbnailbooleannoInclude thumbnail URLs when available.

download_mode comparison

url

Returns validated media URLs when source allows it. Best for server-side workflows that can handle expiring signed URLs.

metadata_only

Returns post and media metadata without download URLs. Best for testing, indexing and previews.

proxy

Returns temporary /v1/download/:token links. The API streams media and does not store videos permanently.

Code examples

JavaScript

const response = await fetch("https://api.clipmagic.ru/v1/threads/video", {
  method: "POST",
  headers: { "Content-Type": "application/json", "X-API-Key": process.env.THREADS_API_KEY },
  body: JSON.stringify({ url: "https://www.threads.net/@example/post/example", download_mode: "metadata_only" })
});
const data = await response.json();

Python

import os, requests
response = requests.post(
  "https://api.clipmagic.ru/v1/threads/video",
  headers={"X-API-Key": os.environ["THREADS_API_KEY"]},
  json={"url": "https://www.threads.net/@example/post/example", "download_mode": "proxy"},
  timeout=15,
)
print(response.json())

Responses

Success response

{
  "success": true,
  "source": "threads",
  "input_url": "https://www.threads.net/@example/post/example",
  "normalized_url": "https://www.threads.net/@example/post/example",
  "post": { "id": "123", "username": "example", "permalink": "https://www.threads.net/@example/post/example", "text": "Caption" },
  "media": [{ "type": "video", "download_url": "https://api.clipmagic.ru/v1/download/dlt_example", "quality": "720p", "duration_seconds": 12.4 }],
  "meta": { "request_id": "req_example", "processing_time_ms": 184 }
}

Error response

{ "success": false, "error": { "code": "CONTENT_NOT_ACCESSIBLE", "message": "The Threads post is not publicly accessible or cannot be processed without authorization." }, "meta": { "request_id": "req_example", "processing_time_ms": 122 } }

Error code table

INVALID_URLThe URL is malformed.
INVALID_CURSORThe comments cursor is expired, tampered, or does not match the URL/limit.
INVALID_QUERYThe search phrase, type, limit or request shape is invalid.
UNSUPPORTED_DOMAINThe URL is not a supported Threads domain.
VIDEO_NOT_FOUNDNo public video was found.
CONTENT_NOT_ACCESSIBLEThe post requires login, is private, unavailable or blocked by challenge.
SOURCE_TIMEOUTThreads source did not respond in time.
RATE_LIMIT_EXCEEDEDThe API key exceeded its configured limit.
DOWNLOAD_TOKEN_EXPIREDThe proxy download token expired.
DOWNLOAD_TOKEN_CONSUMEDA single-use token has already been used.

Proxy download flow

Use download_mode=proxy, then call the returned download_url. HEAD /v1/download/:token checks headers without consuming single-use tokens. GET /v1/download/:token streams from the upstream source and enforces byte limits during streaming.

Range requests are supported when the upstream source supports them. Videos are not stored permanently.

Rate limits and beta limitations

Default beta limits are 30 requests per minute, 500 requests per day and 1 GB daily proxy bandwidth unless your key record says otherwise. Every comments page and search call is one request; credit-mode keys spend one credit after validation. Live Threads extraction reliability depends on public source availability.

FAQ

Does this bypass login or CAPTCHA?

No. It resolves only public or otherwise authorized content and does not use user cookies.

Do proxy links store video files?

No. The proxy streams bytes and enforces limits; it does not permanently store media.

How do I report a bug?

Send the request ID, endpoint, approximate time, error code and URL category to support@clipmagic.ru. Do not send private credentials.

Where is the changelog?

See docs/Status.md in the repository or the deployment changelog maintained by the operator.