TikTok Transcript API reference

Use the TikTok Transcript API to turn the speech in a public TikTok video into text your application can work with. Submit one video URL, keep the returned job identifier, and retrieve the transcript after background processing finishes. Completed results include readable text and timestamped segments.

This reference covers the authenticated developer API. The free website tool also has a guest flow, documented separately below. Both process public TikTok videos, but they use different authentication and allowances. Choose the developer API for application code, repeatable workflows, account activity, and paid usage.

Base URL

All developer requests use HTTPS:

text
https://tiktoktranscriptapi.com/api/v1

Requests and responses use UTF-8 JSON. Set Content-Type: application/json when sending a body and include an Authorization header on every authenticated request. Call the API from your server, command-line tool, or a trusted integration service. Keep your API key away from browser bundles and public forms.

The examples use environment variables for secrets. A name such as JOB_ID or VIDEO_ID is a placeholder, not a working resource. Replace it with the identifier returned by your own request or the ID of a real video you are authorized to process.

Endpoints

MethodPathPurposeCredit cost
POST/transcriptionsSubmit a public TikTok videoOne credit reserved per new job
GET/transcriptions/{id}Retrieve a job and its resultNo credit charge
GET/transcriptions?limit=20List recent jobs in your accountNo credit charge
GET/creditsRetrieve your available balance and planNo credit charge
GET/openapiDownload the machine-readable API specificationNo authentication or credit charge

The API operates on individual public videos. It does not discover videos, search hashtags, crawl profiles, retrieve comments, or bypass account permissions. If your workflow begins with a collection of URLs, select each video in your own application and submit it as an individual job.

Authentication

Create an API key in your dashboard. Give it a name that identifies the application or environment using it. The secret begins with tt_live_ and is displayed once. The dashboard retains a short prefix so you can recognize the key later, but it cannot show you the original secret again.

Include the key in a bearer authorization header:

bash
export TIKTOK_API_KEY='YOUR_API_KEY'

curl https://tiktoktranscriptapi.com/api/v1/credits \
  -H "Authorization: Bearer $TIKTOK_API_KEY"

Every active key belongs to one account. Keys for the same account share the credit balance, request rate, job concurrency, and transcript history. Creating a new key does not create an additional allowance. A key can submit requests and read the account's transcripts, so treat it as an application secret.

Accounts can keep up to ten active keys. Use separate keys for independent integrations so one can be revoked without interrupting the others. If a key is exposed, revoke it, create a replacement, update your server secret, and verify a request using the new value. Requests with a revoked key return HTTP 401 immediately after revocation is recorded.

The account dashboard uses a secure sign-in session established through an email code. That browser session is not the developer API credential. Use bearer keys for API clients, even if the same browser is already signed in to the website.

Quick start

The following request submits a video and assigns a caller-generated idempotency key. Reuse that key if a network failure leaves you unsure whether the request was accepted. Use a new key for a genuinely new transcription request.

bash
curl --fail-with-body \
  https://tiktoktranscriptapi.com/api/v1/transcriptions \
  -H "Authorization: Bearer $TIKTOK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: campaign-brief-video-001" \
  -d '{"url":"https://www.tiktok.com/@creator/video/VIDEO_ID"}'

A newly accepted request returns HTTP 202:

json
{
  "data": {
    "id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
    "status": "processing",
    "status_url": "/api/v1/transcriptions/aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
    "credits_reserved": 1,
    "reused": false
  }
}

Wait at least a few seconds, then request the returned status URL with the same account's API key. The example identifier above is illustrative. A real identifier comes from your own create response. Processing speed depends on the source video, access conditions, audio length, and current queue.

Create a transcript

Send POST /transcriptions with a JSON object containing url. This call validates the source, reserves a credit, creates a job, and queues the video for processing. The HTTP response does not wait for the full transcript.

FieldTypeRequiredMeaning
urlstringYesOne public TikTok video URL; maximum 2,048 characters
json
{
  "url": "https://www.tiktok.com/@creator/video/VIDEO_ID"
}

The request body must be no larger than 16 KiB. A JSON object is required; a bare string, array, malformed JSON, or an empty body is rejected. Extra request properties do not enable additional processing options. The currently supported input is the video URL.

A successful create response includes the job ID, its current status, a relative status URL, whether the request reused an earlier job, and the number of credits newly reserved by this call. The HTTP Location header also points to the status URL. Store the job ID together with your own source record so you can reconnect the result to the correct task.

Each new job covers up to the first 20 minutes of one video's audio. This limit applies to the trial, monthly plan, and annual plan. It is a per-video processing limit, not a guarantee that every accepted URL will produce 20 minutes of speech. Shorter videos return only their available content.

The service can process a maximum of five jobs at once per account. If that limit is reached, wait for a current job to finish. Listing recent jobs shows the last synchronized status; retrieving an individual job refreshes its status from processing. The dashboard and background reconciliation also refresh completed and failed work.

Use a canonical public video URL whenever it is available:

text
https://www.tiktok.com/@creator/video/1234567890123456789

Active public share links on vm.tiktok.com and vt.tiktok.com are also accepted. They must resolve to a video that the processing service can access. A short link can become invalid after it is shared, so retain the original full video URL in your source system when possible.

The server checks the hostname and video path before creating a job. A profile page, hashtag page, search result, collection, image-only post, or a URL on another platform is not an individual supported video input. A lookalike hostname such as tiktok.com.example.org does not qualify as a TikTok domain.

A syntactically valid URL can still fail during processing. The video may have been removed, made private, restricted to signed-in viewers, or blocked from access in the processing environment. The source must be available without sharing a personal TikTok login. The API does not accept your TikTok password, cookies, or account tokens.

Submit media you own or are authorized to process. If you are developing a customer-facing application, explain this requirement in your upload or URL submission flow. The transcript output should remain associated with the video and the permissions under which you obtained it.

Idempotent requests

The optional Idempotency-Key header makes retries safe. The key identifies one logical create operation within your account. Use 8–128 characters consisting of letters, numbers, underscores, hyphens, periods, or colons. A UUID is a convenient choice.

bash
curl https://tiktoktranscriptapi.com/api/v1/transcriptions \
  -H "Authorization: Bearer $TIKTOK_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 7d1729c9-659a-4610-920a-12b4ce0d9829" \
  -d '{"url":"https://www.tiktok.com/@creator/video/VIDEO_ID"}'

Repeating the same key with the same URL returns the original job and does not reserve another credit. The reused response returns HTTP 200 and sets reused to true and credits_reserved to zero. A repeated key with a different URL returns HTTP 409, because changing the input would make the operation ambiguous.

Without an idempotency key, every accepted POST is a separate job. Submitting the same URL twice can therefore consume two credits. URL equality alone is not a deduplication rule. If your workflow retries requests, generate the key before making the first network call and save it with the pending operation.

Use the original key only to recover the original request. To intentionally run a video again—for example, after the source becomes publicly available—start a new logical operation with a new key. A failed job remains the result of its original operation; retrying its idempotency key does not create a replacement job.

Retrieve a transcript

Send GET /transcriptions/{id} using a key from the account that created the job. This endpoint returns the current state and, on success, the full result.

bash
curl https://tiktoktranscriptapi.com/api/v1/transcriptions/JOB_ID \
  -H "Authorization: Bearer $TIKTOK_API_KEY"

A completed response has this shape:

json
{
  "data": {
    "id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
    "status": "completed",
    "filename": "TikTok video",
    "created_at": "2026-09-07T09:00:00.000Z",
    "duration_seconds": 8,
    "text": "Start with a clear question. Show the process, then share what you learned.",
    "segments": [
      { "start": 0, "end": 2.4, "text": "Start with a clear question." },
      { "start": 2.4, "end": 8.2, "text": "Show the process, then share what you learned." }
    ]
  }
}
FieldTypeMeaning
idstringStable transcript job identifier
statusstringprocessing, completed, or failed
filenamestringDisplay name assigned to the imported video
created_atstringJob creation timestamp in ISO 8601 format
duration_secondsnumber or nullDuration reported by the processor when available
textstring or nullFull transcript when completed; null before completion or after failure
segmentsarray or nullTimed transcript segments when completed and available
errorobjectPresent when processing fails; contains a code and message

Segment start and end values are seconds relative to the source audio. They can include fractional seconds. Do not interpret them as Unix timestamps or milliseconds. Use the segment end field directly when constructing subtitles; do not assume every segment has the same length or ends when the next one begins.

The filename is a display field, not an authentication or ownership signal. Use the job ID for lookups. Result text can contain punctuation, line breaks, non-English characters, or words you did not expect. Render it as text in your application, never as trusted HTML.

A completed result may contain little text if the video has little recognizable speech. Background music, overlapping voices, rapid cuts, and noise can affect transcription quality. Review quotes and captions before publishing them or using them as a source of record.

Job lifecycle

A new job begins in processing. Your application should show a pending state and retain the ID even if the user navigates away. Continue reading the same job rather than creating another request to check progress.

The terminal states are completed and failed. A completed job has finished processing and its output can be saved. A failed job has stopped processing; the result describes the failure in the error object and the reservation is released. Stop polling when either terminal state appears.

json
{
  "data": {
    "id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
    "status": "failed",
    "filename": "TikTok video",
    "created_at": "2026-09-07T09:00:00.000Z",
    "duration_seconds": null,
    "text": null,
    "segments": null,
    "error": {
      "code": "transcription_failed",
      "message": "This video could not be processed. Check that it is public and playable. The reserved credit has been released."
    }
  }
}

A failed transcription is different from an unsuccessful HTTP status request. For example, an HTTP 503 while checking a job says the status could not be retrieved at that moment. It does not establish that the underlying video failed. Keep the ID and retry the read after a delay.

The API does not currently expose job cancellation, webhooks for transcript completion, or a percentage-complete field. Disconnecting your client or closing the dashboard does not cancel work already queued. Build your interface around a pending state and the two terminal states rather than inventing a progress percentage.

List recent transcripts

Use the list endpoint to recover recent IDs or display account history:

bash
curl 'https://tiktoktranscriptapi.com/api/v1/transcriptions?limit=20' \
  -H "Authorization: Bearer $TIKTOK_API_KEY"

The optional limit parameter defaults to 20 and accepts integers from 1 to 100. Results are ordered newest first. The response contains a data array with id, status, source_url, and created_at for each job.

json
{
  "data": [
    {
      "id": "aaaaaaaa-bbbb-4ccc-8ddd-eeeeeeeeeeee",
      "status": "completed",
      "source_url": "https://www.tiktok.com/@creator/video/VIDEO_ID",
      "created_at": "2026-09-07T09:00:00.000Z"
    }
  ]
}

An empty array is a valid result for an account with no jobs. The list does not include transcript text or segment arrays. Retrieve a specific job to obtain its output and refresh its processing status. Because list statuses reflect the latest synchronization, a recently finished job may still appear as processing until it is refreshed.

This endpoint is a recent-history view, not a paginated archival export. It does not currently accept a cursor, offset, or date filter. Keep the job IDs and completed output your application needs in your own storage instead of treating the latest 100 records as a complete long-term history.

Credits and plans

New verified accounts start with 100 free API credits. A new transcript reserves one credit at submission. Successful processing uses that credit. If the job fails, reconciliation releases the reserved credit to the balance it came from, subject to the expiration of monthly allowance.

The monthly plan costs $5 per month and grants 1,000 credits each month. The annual plan costs $54 per year, equivalent to $4.50 per month, and also grants 1,000 credits each month. Annual billing does not grant all twelve months of credits at once. Monthly allowances refresh on the subscription's monthly anniversary while paid access remains active.

Unused monthly credits do not roll over. Trial credits and purchased top-up credits are tracked separately. The service uses active monthly allowance first, then top-up credits, then trial credits. A failed job returns its reservation to the same bucket. If that monthly grant has already expired, releasing a reservation does not increase the new month's allowance.

Subscribers can buy 1,000 additional credits for $2.50 on the monthly plan or $1.50 on the annual plan. An active subscription is required to purchase a top-up. Top-up credits remain available after cancellation. Account rate limits follow the currently active plan, so an account without an active subscription uses the trial rate even if top-up credits remain.

Retrieve your available credits programmatically:

bash
curl https://tiktoktranscriptapi.com/api/v1/credits \
  -H "Authorization: Bearer $TIKTOK_API_KEY"

The balance endpoint returns available, trial, monthly, topup, plan, and monthly_refresh_at inside data. Availability is the current sum of the applicable balances. A processing job has already reserved its credit, so that credit is not included in the available total.

Purchases occur through Stripe Checkout linked from your authenticated dashboard. Credit activation depends on verified payment status; returning to a success page alone does not establish payment. Subscription status and top-up grants are reconciled from Stripe, with duplicate event handling to avoid awarding the same purchase twice.

Rate and concurrency limits

AccountAPI requests per minuteConcurrent processing jobs
Free trial or no active subscription205
Monthly subscription2005
Annual subscription3005

Create calls and authenticated result, list, and balance reads count toward the request rate. Reading status does not consume a transcript credit, but it still uses request capacity. The allowance is shared across your account's keys and supported interfaces; adding more keys does not increase it.

The rate window follows UTC calendar minutes. When you reach a limit, the API responds with HTTP 429 and a Retry-After header. Wait for that many seconds before retrying. Avoid immediately retrying failed requests from several workers at once, since this can create another burst at the next window boundary.

Concurrency limits protect processing capacity independently of the request rate. A plan can allow 200 requests per minute while still limiting the account to five processing jobs. Use a queue in your application, refresh the oldest pending jobs, and release local queue slots only when jobs reach a terminal state.

For polling, a delay of three to five seconds is a reasonable starting point for one job. Increase it when you have several jobs pending, and use a maximum waiting time appropriate to your interface. Store the job ID so the user can return later if your interactive wait ends.

Error handling

Transport and validation errors use an HTTP status and a JSON error object:

json
{
  "error": {
    "code": "invalid_source",
    "message": "Provide one public TikTok video URL in the url field."
  }
}
HTTP statusCommon codeRecommended response
400invalid_jsonSend a valid JSON object
400invalid_sourceCheck that the URL identifies a supported public video
400invalid_limitUse an integer between 1 and 100
400invalid_idempotency_keyCorrect the idempotency-key format
401invalid_api_keyCheck the bearer header and whether the key was revoked
402credits_exhaustedAdd credits or choose a paid plan
404not_foundCheck the job ID and the account that created it
409idempotency_conflictReuse the original input or start a new logical operation
413body_too_largeSend a JSON body smaller than 16 KiB
415unsupported_media_typeSet Content-Type to application/json
429rate_limitedWait according to Retry-After
429concurrency_limitWait for current processing jobs to finish
503service_unavailableKeep your operation ID and retry after a delay

Your application should branch on the HTTP status and stable code rather than matching the exact English message. Messages explain the current issue and may become more specific over time. Never display a raw exception or secret-bearing request header to the person using your application.

A 404 also protects account boundaries: a key cannot retrieve another account's transcript by guessing its ID. If a known job appears missing, check the account associated with the key and compare the ID with your saved create response. Avoid creating another transcript until you have ruled out a simple account or identifier mismatch.

Retry strategy

Retry read requests after temporary network failures or HTTP 503 responses using a bounded delay. Start with a few seconds, increase the wait after repeated failures, and stop after your chosen deadline. Keep the job ID so a later request can resume the workflow without starting a new transcript.

For HTTP 429, use the server's Retry-After value. For validation, authentication, and credit errors, fix the underlying issue before making another request. Repeatedly sending the same invalid URL or revoked key will not resolve the problem.

For create requests, use an idempotency key before enabling automatic retries. A timeout can occur after the job is committed but before your client receives the response. Repeating the same logical operation with its original key returns the existing job instead of reserving another credit.

Do not automatically create a new job after a transcription reaches failed. The source may still be inaccessible, and repeating it can waste processing attempts. Ask the caller to check the video's public availability or choose a different source. If they intentionally retry, create a new operation ID.

JavaScript example

This Node.js example reads the API key and video URL from environment variables, submits a job, and polls for a terminal state. It keeps the create idempotency key stable for retry attempts. Use Node.js with built-in fetch support.

javascript
import { randomUUID } from 'node:crypto';
import { setTimeout as delay } from 'node:timers/promises';

const base = 'https://tiktoktranscriptapi.com/api/v1';
const key = process.env.TIKTOK_API_KEY;
const video = process.env.TIKTOK_VIDEO_URL;
if (!key || !video) throw new Error('Set TIKTOK_API_KEY and TIKTOK_VIDEO_URL');

async function api(path, options = {}) {
  for (let attempt = 0; attempt < 4; attempt++) {
    let response;
    try {
      response = await fetch(base + path, {
        ...options,
        headers: {
          Authorization: `Bearer ${key}`,
          'Content-Type': 'application/json',
          ...options.headers,
        },
        signal: AbortSignal.timeout(30000),
      });
    } catch (error) {
      if (attempt === 3) throw error;
      await delay(2000 * (attempt + 1));
      continue;
    }
    if ((response.status === 429 || response.status >= 500) && attempt < 3) {
      const retry = Number(response.headers.get('retry-after'));
      await delay((Number.isFinite(retry) && retry > 0 ? retry : 3 * (attempt + 1)) * 1000);
      continue;
    }
    const body = await response.json();
    if (!response.ok) throw new Error(`${response.status}: ${body.error?.message}`);
    return body.data;
  }
  throw new Error('Request retries exhausted');
}

const operationId = randomUUID();
const created = await api('/transcriptions', {
  method: 'POST',
  headers: { 'Idempotency-Key': operationId },
  body: JSON.stringify({ url: video }),
});
console.log('Save this job ID:', created.id);

const deadline = Date.now() + 10 * 60 * 1000;
while (Date.now() < deadline) {
  await delay(5000);
  const job = await api(`/transcriptions/${created.id}`);
  if (job.status === 'completed') {
    console.log(job.text);
    break;
  }
  if (job.status === 'failed') throw new Error(job.error.message);
}

The interactive polling deadline does not cancel the job. If the loop ends while processing continues, show the stored job ID and let your application retrieve it later. In a production worker, persist the operation and job IDs in durable storage instead of relying only on process memory.

Python example

This example uses requests for HTTP calls. It handles temporary response errors and uses the same operation key across create retries. Set your API key and source URL in the environment before running the script.

python
import os
import time
import uuid
import requests

base = 'https://tiktoktranscriptapi.com/api/v1'
key = os.environ['TIKTOK_API_KEY']
video = os.environ['TIKTOK_VIDEO_URL']
client = requests.Session()
client.headers.update({'Authorization': f'Bearer {key}'})

def api(method, path, **kwargs):
    for attempt in range(4):
        try:
            response = client.request(method, base + path, timeout=30, **kwargs)
        except requests.RequestException:
            if attempt == 3:
                raise
            time.sleep(2 * (attempt + 1))
            continue
        if (response.status_code == 429 or response.status_code >= 500) and attempt < 3:
            retry_after = response.headers.get('Retry-After', '')
            wait = int(retry_after) if retry_after.isdigit() else 3 * (attempt + 1)
            time.sleep(max(1, wait))
            continue
        body = response.json()
        if not response.ok:
            message = body.get('error', {}).get('message', 'Request failed')
            raise RuntimeError(f'{response.status_code}: {message}')
        return body['data']
    raise RuntimeError('Request retries exhausted')

operation_id = str(uuid.uuid4())
created = api('POST', '/transcriptions',
              headers={'Idempotency-Key': operation_id},
              json={'url': video})
print('Save this job ID:', created['id'])

deadline = time.monotonic() + 600
while time.monotonic() < deadline:
    time.sleep(5)
    job = api('GET', '/transcriptions/' + created['id'])
    if job['status'] == 'completed':
        print(job['text'])
        break
    if job['status'] == 'failed':
        raise RuntimeError(job['error']['message'])
else:
    print('Still processing. Retrieve the saved job ID later.')

Treat the response as structured data. Save text when you need a readable transcript and segments when you need to attach quotes to timestamps. Handle null result fields before completion instead of assuming the first response already contains usable text.

Text and subtitle exports

The developer API returns JSON. Save the text field as a UTF-8 .txt file when you need a plain transcript. For subtitle exports, convert each segment's start, end, and text into the output format required by your editor. The public web tool already provides TXT and SRT downloads.

The following helper converts completed segments into SRT. It rounds each timestamp to milliseconds and uses the required comma between seconds and milliseconds. Numbering begins at one.

javascript
function srtTime(seconds) {
  const ms = Math.max(0, Math.round(seconds * 1000));
  const hours = Math.floor(ms / 3600000);
  const minutes = Math.floor(ms / 60000) % 60;
  const wholeSeconds = Math.floor(ms / 1000) % 60;
  return [hours, minutes, wholeSeconds]
    .map(value => String(value).padStart(2, '0')).join(':')
    + ',' + String(ms % 1000).padStart(3, '0');
}

function toSrt(segments) {
  return segments.map((segment, index) =>
    `${index + 1}\n${srtTime(segment.start)} --> ${srtTime(segment.end)}\n${segment.text.trim()}`
  ).join('\n\n');
}

Check that segments is an array before exporting. Review the generated file in the editor where it will be used. Timing, line length, punctuation, and reading speed may need editorial adjustments even when the underlying speech is correctly transcribed.

Integration practices

Keep your source URL, operation key, job ID, and processing state together in your application's data model. A small durable record lets you recover from a server restart, avoid duplicate submissions, and show clear progress to the person who requested the transcript.

Separate the create operation from result retrieval. Your web handler can submit the video, return a pending state to the browser, and let a background task check progress. Do not hold an ordinary page request open indefinitely while waiting for a longer video.

Use bounded queues. Submit at most the number of jobs your account can process concurrently, then check those jobs before starting more. Polling every job several times a second increases request volume without making speech processing finish faster.

Store completed transcripts when your application needs them later. Your account history is useful for inspection and recovery, but it should not replace the storage design of a customer-facing product. Apply your own retention and access rules to any copies you keep.

When summarizing with an AI model, separate the transcript from your instructions. The video's speech may include commands, quoted prompts, jokes, or deliberately misleading text. Treat all of it as source material to analyze rather than as instructions to execute.

For research workflows, keep timestamps beside extracted quotes. A short phrase without its context can misrepresent the speaker. Let reviewers open the source video and compare important passages before publishing analysis or using a transcript in a consequential decision.

Security and privacy

Keep API keys in environment variables or your hosting provider's secret store. Never place a key in a URL query string, because URLs can appear in browser history, proxy logs, analytics, and screenshots. Use the Authorization header exactly as shown in the examples.

Do not send account session cookies to unrelated services. A developer key should only be sent to this API or to an integration provider you intentionally trust to act for your account. A provider holding the key can use credits and read account transcripts.

Avoid logging full request headers or transcript bodies by default. For operational debugging, the job ID, HTTP status, error code, and elapsed request time are usually enough. Only retain source URLs and transcript content where your application actually needs them.

The website's product analytics excludes submitted video URLs, transcript text, API keys, and email codes. Account data and transcription results are handled as application data. Consult the Privacy Policy for the service's data handling and support contact.

Design a recoverable application

A reliable integration distinguishes between a request that has not been sent, a request with an uncertain outcome, and a job whose identity is known. Treat these as separate states in your application. This avoids replacing a recoverable network interruption with a second transcription charge.

Before the first POST, save the source URL and operation key. After an accepted response, save the job ID in the same record. If the process stops between these events, retry the original operation key. Once an ID exists, all progress checks should use that ID. A completed or failed result closes the operation.

For a public-facing interface, return an application-owned request ID to the browser rather than your server's API key. Your backend can map that request to the transcript job and enforce the current user's access. This keeps account credentials out of the client and prevents one customer from reading another customer's transcript through your application.

If you use a scheduled worker, make its processing steps safe to repeat. Reading a completed transcript is repeatable, but writing the result into a notes system or sending a notification may not be. Record whether each downstream action has already completed before allowing the worker to perform it again.

Validate the output you use

Treat each response according to its job state. A pending result with null text is normal; it should not be rendered as an empty finished transcript. Only run summarization or export code once status is completed. For a failed state, show the error and the source link rather than presenting an empty document as a success.

Check types at your application's boundary. Segment arrays may be unavailable, and duration can be null. Preserve fractional seconds for timing calculations. When presenting a whole-number duration to a person, format a display value without changing the original segment times stored for later export.

Do not depend on a particular number of segments or a fixed relationship between word count and duration. Different speech, silence, edits, and audio quality produce different segmentation. Your layout should handle one short segment, a longer transcript with many segments, and a completed result with very little speech.

Transcripts can contain the same sensitive information that was spoken in the source video. If your application forwards text to another service, make that destination and purpose clear to your users. Apply the same access controls to generated summaries and exported files as you apply to the original transcript.

Diagnose a stalled workflow

Begin with the last confirmed step. If you have a job ID, retrieve it with the same account's key. If you only have an operation key, repeat the create request with the original source. If you have neither, check your application's request logs and the account's recent activity before submitting again.

A job shown as processing in the recent list may simply need an individual status refresh. The list is optimized for recent account activity; it does not force every underlying job to refresh on every read. The individual result endpoint and the dashboard perform that synchronization.

If the service returns rate-limited responses, reduce polling volume across the entire account. Several integrations using separate keys still share one rate window. A single worker with a small queue and a sensible delay is often easier to operate than many clients independently polling the same jobs.

When contacting support about a stall, describe the sequence: whether create returned an ID, whether a status read succeeded, the most recent job state, and any HTTP error. This gives enough context to investigate without exposing your key or copying the entire transcript into an email.

Guest website endpoints

The public form uses POST /api/transcribe-link and GET /api/transcriptions. These are outside the /api/v1 namespace and use a guest-session cookie. They are intended for the no-account website experience, which currently allows one free transcript daily, up to 20 minutes.

A terminal client can preserve that session with a cookie jar:

bash
curl --cookie cookies.txt --cookie-jar cookies.txt \
  https://tiktoktranscriptapi.com/api/transcribe-link \
  -H 'Content-Type: application/json' \
  -d '{"url":"https://www.tiktok.com/@creator/video/VIDEO_ID"}'

curl --cookie cookies.txt \
  https://tiktoktranscriptapi.com/api/transcriptions

The create response uses transcriptionId rather than data.id. The list response is an array of records containing id, filename, status, text, durationSeconds, and segments. Match the returned ID to your own job. Without the session cookie, the guest list is empty.

Guest cookies do not authenticate the paid developer API. Developer keys do not replace guest cookies. Keep the two flows separate in your integration: use /api/v1 when you need account credits, idempotency, and a stable application credential.

Support

If a request is not behaving as expected, include the endpoint, HTTP status, error code, approximate time, and job ID in your support message. Describe what you expected and what you received. Do not include API keys, session cookies, sign-in codes, or payment card details.

Open support, review the billing guide, or return to the quickstart. For agent integrations, the MCP guide explains how the same jobs and credits are exposed as tools.