> ## Documentation Index
> Fetch the complete documentation index at: https://docs.vidnavigator.com/llms.txt
> Use this file to discover all available pages before exploring further.

# TikTok LIVE Search

> Search TikTok LIVE rooms broadcasting right now for a keyword, and return a `task_id` immediately. Poll `GET /tiktok/live/search/{task_id}` for cursor-paginated results. Each room comes with its author, live counters (`stats.viewers`, likes, ...), `hashtags`, `category`, `game_tags` and, unless `include_stream_urls` is `false`, its playback URLs (FLV and HLS by quality, plus an audio-only stream). Results are retained for ~1 hour.

Results keep TikTok's ranking and are localized to `country`. TikTok serves about 50 rooms per keyword; some keywords have no live room in a given country at a given time, which completes with zero results.

**Billing:** 1 `residential_request` per 30 rooms TikTok returned (`stats.rooms_fetched`), minimum 1 per search. A keyword typically yields up to about 45 rooms, so 1 or 2 residential requests.

**Usage disclosure:** This endpoint does NOT accept `include_usage`. Pass `include_usage=true` on `GET /tiktok/live/search/{task_id}` instead.

Find TikTok LIVE rooms broadcasting right now for a keyword, with their stream URLs, and get a `task_id` back immediately.

## Overview

This endpoint searches TikTok's LIVE tab: it returns the rooms that are live **at the moment the search runs**, not past videos. Each room comes with its author, live counters (current viewers, likes, ...), hashtags, category and playback URLs (FLV and HLS by quality, plus an audio-only stream).

It is asynchronous: you poll [`GET /tiktok/live/search/{task_id}`](#get-the-result) for cursor-paginated rooms, or wait for the [webhook](https://docs.vidnavigator.com/webhooks.md). Results are retained for \~1 hour.

* Rooms keep **TikTok's ranking**.
* Results are **localized to `country`** (default `us`): the same keyword returns different rooms in different countries.
* TikTok serves about **50 rooms per keyword**. A keyword with no LIVE room in that country at that moment completes with zero results.
* A search usually takes 20 to 50 seconds.

> [!NOTE]
>
> Looking for regular TikTok videos? Use [TikTok Keyword Search](https://docs.vidnavigator.com/api-reference/endpoint/tiktok-search.md). LIVE search returns rooms that are broadcasting now, each shaped like a keyword search result (`id`, `author`, `stats`, `hashtags`) plus LIVE-only fields.

## Billing

* **1 `residential_request` per 30 rooms TikTok returned** (`stats.rooms_fetched`, including rooms past `max_results`), minimum 1 per search. A keyword typically yields up to about 45 rooms, so 1 or 2 residential requests.
* Stream URLs cost nothing extra: they come in the same TikTok response.
* **No `search_request`** is billed. A failed search is fully refunded.

> [!WARNING]
>
> **Usage disclosure:** this endpoint does **not** accept `include_usage`. Billing happens after the `202` response is sent. Pass `include_usage=true` on [`GET /tiktok/live/search/{task_id}`](#get-the-result) instead.

## Request Parameters

| Parameter | Type | Required | Description |
| - | - | - | - |
| `query` | string | Yes | Keyword phrase to search LIVE rooms for (min length 2), e.g. `gaming`, `music`, `football`. |
| `max_results` | integer | No | Upper bound on rooms collected. `0` (default) or omitted means as many as TikTok serves, about 50. |
| `country` | string | No | Two-letter country code (ISO 3166-1 alpha-2, lowercase or uppercase) whose LIVE rooms you get. Default `us`. The request schema above lists the accepted codes; an unsupported code returns `400 invalid_country` with the list. |
| `include_stream_urls` | boolean | No | Default `true`: each room carries its `stream_urls`. Pass `false` to leave them out. |
| `webhook_url` | string | No | Where to POST a notification when the task finishes. Overrides the account default set in [Studio → API](https://vidnavigator.com/studio/api); pass `""` to opt this task out of the default. Must be a public `https` URL. The event carries `stats` and points you to `check_status_url` for the rooms. See [Webhooks](https://docs.vidnavigator.com/webhooks.md). |

## Example Usage

```bash cURL theme={null}
curl -X POST "https://api.vidnavigator.com/v1/tiktok/live/search" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "gaming",
    "country": "us",
    "max_results": 20
  }'
```

```python Python theme={null}
import requests

response = requests.post(
    "https://api.vidnavigator.com/v1/tiktok/live/search",
    headers={"X-API-Key": "YOUR_API_KEY", "Content-Type": "application/json"},
    json={"query": "gaming", "country": "us", "max_results": 20},
)
task = response.json()
print("Task ID:", task["data"]["task_id"])
```

```javascript JavaScript theme={null}
const response = await fetch('https://api.vidnavigator.com/v1/tiktok/live/search', {
  method: 'POST',
  headers: {
    'X-API-Key': 'YOUR_API_KEY',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ query: 'gaming', country: 'us', max_results: 20 })
});

const task = await response.json();
console.log('Task ID:', task.data.task_id);
```

## Success Response (202 Accepted)

```json theme={null}
{
  "status": "success",
  "data": {
    "task_id": "6f1c2a8e-4b3d-4e0a-9c55-2d7f1e8b9a10",
    "task_status": "processing",
    "query": "gaming",
    "country": "us",
    "max_results": 20,
    "include_stream_urls": true,
    "expires_at": "2026-11-05T15:00:00Z",
    "check_status_url": "/v1/tiktok/live/search/6f1c2a8e-4b3d-4e0a-9c55-2d7f1e8b9a10",
    "webhook_url": null,
    "message": "Search started. Poll check_status_url for results."
  }
}
```

## Get the result

`GET /tiktok/live/search/{task_id}` — poll this endpoint with the `task_id` (or the `check_status_url`) returned above, or wait for the [webhook](https://docs.vidnavigator.com/webhooks.md) notification. Polling does **not** consume credits.

> [!NOTE]
>
> The playground above only covers the submit request. Call the result endpoint with cURL or your HTTP client.

### Request Parameters

| Parameter | In | Required | Description |
| - | - | - | - |
| `task_id` | path | Yes | Task ID returned by `POST /tiktok/live/search` |
| `cursor` | query | No | Opaque pagination cursor from a previous response |
| `limit` | query | No | Maximum number of rooms to return, between `1` and `500`. Default is `50`. |
| `include_usage` | query | No | When `true` and `task_status=completed`, attach a `usage` block: 1 `residential_request` per 30 `rooms_fetched`, minimum 1. |

### Polling Lifecycle

* `processing`: the search is still running (`results` is empty)
* `completed`: the rooms are ready
* `failed`: the search ended with an error (all charges refunded)

### Example Requests

```bash cURL theme={null}
curl "https://api.vidnavigator.com/v1/tiktok/live/search/6f1c2a8e-4b3d-4e0a-9c55-2d7f1e8b9a10?limit=25&include_usage=true" \
  -H "X-API-Key: YOUR_API_KEY"
```

```python Python theme={null}
import requests

response = requests.get(
    "https://api.vidnavigator.com/v1/tiktok/live/search/6f1c2a8e-4b3d-4e0a-9c55-2d7f1e8b9a10",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"limit": 25, "include_usage": "true"},
)
print(response.json())
```

```javascript JavaScript theme={null}
const response = await fetch(
  'https://api.vidnavigator.com/v1/tiktok/live/search/6f1c2a8e-4b3d-4e0a-9c55-2d7f1e8b9a10?limit=25&include_usage=true',
  { headers: { 'X-API-Key': 'YOUR_API_KEY' } }
);
const result = await response.json();
```

### Example Completed Response

```json theme={null}
{
  "status": "success",
  "data": {
    "task_id": "6f1c2a8e-4b3d-4e0a-9c55-2d7f1e8b9a10",
    "task_status": "completed",
    "query": "gaming",
    "country": "us",
    "stats": {
      "pages_fetched": 1,
      "rooms_fetched": 44,
      "results_count": 20,
      "has_more": true,
      "country": "us"
    },
    "results": [
      {
        "id": "7704440240265644830",
        "title": "Ranked grind #fortnite",
        "url": "https://www.tiktok.com/@creator/live",
        "started_at": "2026-11-04T22:04:46Z",
        "author": {
          "id": "6628548115959152646",
          "unique_id": "creator",
          "nickname": "Creator",
          "sec_uid": "MS4wLjABAAAA...",
          "followers": 576168,
          "avatar_url": "https://p16-common-sign.tiktokcdn-us.com/..."
        },
        "stats": {
          "viewers": 1296,
          "total_viewers": 232347,
          "likes": 301154,
          "comments": 12839,
          "shares": 360
        },
        "hashtags": ["fortnite"],
        "category": "Gaming",
        "game_tags": ["Fortnite"],
        "cover_url": "https://p19-common-sign.tiktokcdn-us.com/...",
        "stream_urls": {
          "default_quality": "hd",
          "flv": {
            "hd": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3867376775231964110_hd.flv?expire=1795089584&sign=..."
          },
          "hls": {
            "hd": "https://pull-hls-f16-tt01.tiktokcdn-us.com/game/stream-3867376775231964110_hd/index.m3u8?expire=1795089584&sign=..."
          },
          "audio_only": "https://pull-f5-tt01.tiktokcdn-us.com/game/stream-3867376775231964110.flv?expire=1795089584&sign=...&only_audio=1",
          "expires_at": "2026-11-19T11:59:44Z"
        }
      }
    ],
    "pagination": {
      "limit": 25,
      "offset": 0,
      "total_items": 20,
      "has_next": false,
      "has_prev": false,
      "next_cursor": null,
      "prev_cursor": null
    },
    "download_url": "https://storage.example.com/api/tiktok_live_searches/user/task.json?X-Amz-Signature=...",
    "webhook": null,
    "created_at": "2026-11-05T14:00:00Z",
    "completed_at": "2026-11-05T14:00:31Z",
    "expires_at": "2026-11-05T15:00:00Z"
  },
  "usage": {
    "charges": [
      { "service_type": "residential_request", "quantity": 2, "credits": 0.01 }
    ],
    "total_credits": 0.01
  }
}
```

### Understanding the Response

#### `stats`

* `rooms_fetched`: distinct rooms TikTok returned, including any past `max_results`. This is what is billed (1 `residential_request` per 30).
* `results_count`: rooms in `results`
* `has_more`: whether TikTok had more rooms when the search stopped
* `pages_fetched`: TikTok pages fetched (up to 50 rooms each)
* `country`: same as `country`

#### `results`

Each room is shaped like a [keyword search result](https://docs.vidnavigator.com/api-reference/endpoint/tiktok-search.md#results), plus LIVE-only fields:

| Field | Description |
| - | - |
| `id` | LIVE room ID |
| `title` | Title the streamer set, or `null` |
| `url` | `https://www.tiktok.com/@username/live` |
| `started_at` | When the LIVE started (UTC, ISO 8601) |
| `author` | `id`, `unique_id` (username), `nickname`, `sec_uid`, `followers`, `avatar_url` |
| `stats` | `viewers` (watching when the search ran), `total_viewers` (since the LIVE started), `likes`, `comments`, `shares`. Counters TikTok does not send are `null`. |
| `hashtags` | Hashtags written in the title, without `#` |
| `category` | The LIVE's category on TikTok, e.g. `Gaming` |
| `game_tags` | Games tagged on the LIVE, e.g. `Fortnite` |
| `cover_url` | Cover image |
| `stream_urls` | Playback URLs (see below). Omitted when `include_stream_urls` is `false`. |

#### `stream_urls`

| Field | Description |
| - | - |
| `default_quality` | The quality TikTok plays by default |
| `flv` | HTTP-FLV URLs keyed by quality: `origin`, `uhd`, `hd`, `sd`, `ld` (only those the LIVE offers) |
| `hls` | HLS (`.m3u8`) URLs with the same keys, when TikTok provides them. Can be empty. |
| `audio_only` | HTTP-FLV URL of the audio-only stream |
| `expires_at` | Expiry of the URL signatures |

The URLs play while the LIVE is on and stop when it ends, whatever `expires_at` says. They work in players such as VLC, `ffplay` or `ffmpeg` (FLV and HLS), and in browsers through `hls.js` (HLS).

#### `download_url`

When present, a short-lived signed URL to the full result as one JSON file (same shape as the paginated `results`, but unsliced). Call the endpoint again to mint a fresh one.

#### `error`

Present when `task_status` is `failed`: an object with `error` (a code you can branch on, e.g. `search_failed`), `message` and `http_status`. See [Errors](https://docs.vidnavigator.com/api-reference/errors.md).

#### `webhook`

Delivery state of the task's [webhook](https://docs.vidnavigator.com/webhooks.md) notification (`status`, `attempts`, `response_status`, `last_error`, `delivered_at`), or `null` when no webhook applies.

### Error Cases

| Status | `error` | When |
| - | - | - |
| `400` | `request_body_required` | No JSON body |
| `400` | `invalid_query` | `query` missing or shorter than 2 characters |
| `400` | `invalid_max_results` | `max_results` negative or not an integer |
| `400` | `invalid_country` | `country` not supported; the message lists the accepted codes |
| `400` | `invalid_include_stream_urls` | `include_stream_urls` not a boolean |
| `400` | `invalid_cursor` | Bad `cursor` on the result endpoint |
| `404` | `task_not_found` | Task does not exist, expired, or belongs to another account |

### Tips

* LIVE rooms change by the minute: run the search when you need the rooms, and read the stream URLs soon after.
* Try several keywords and countries: a keyword can have no LIVE room in one country and dozens in another.
* `stats.viewers` is a snapshot taken when the search ran.


## OpenAPI

````yaml POST /tiktok/live/search
openapi: 3.0.3
info:
  title: VidNavigator Developer API
  description: >-
    The VidNavigator Developer API provides programmatic access to video
    analysis, transcription, and search capabilities.


    ## Authentication

    All endpoints require API key authentication via the `X-API-Key` header:

    ```

    X-API-Key: YOUR_API_KEY

    ```


    ## Rate Limits

    Check the documentation for the rate limits for each endpoint.


    ## Long videos and async jobs

    The speech-to-text endpoints (`/transcribe`, `/extract/video` with
    `transcribe=true`, `/tweet/statement`) run for as long as the media is long.
    A synchronous request holds the HTTP connection open for the whole download
    and transcription, which is reliable for short clips and not for long ones —
    clients, reverse proxies and marketplace gateways all time out.


    **For media longer than ~10 minutes, use the async twin of the endpoint:**


    | Synchronous | Async submit | Poll |

    |---|---|---|

    | `POST /transcribe` | `POST /transcribe/async` | `GET
    /transcribe/{task_id}` |

    | `POST /extract/video` | `POST /extract/video/async` | `GET
    /extract/video/{task_id}` |

    | `POST /tweet/statement` | `POST /tweet/statement/async` | `GET
    /tweet/statement/{task_id}` |


    The async endpoint returns `202` with a `task_id` immediately. Poll the
    `check_status_url` until `task_status` is `completed` or `failed`; results
    are retained for 1 hour after the job finishes. Polling is free.


    The synchronous endpoints enforce a **10-minute** limit, rejecting longer
    media with `video_too_long` (HTTP 400). The metadata fetch needed to read
    the video's duration is billed (`standard_request` or `residential_request`)
    and is **not** refunded: the limit is documented, so the proxy call was
    spent answering a request that could not be served. No `transcription_hour`
    is charged — no audio is processed.


    Past ten minutes a single HTTP connection is not a reliable way to deliver a
    transcription, so send long media to the async endpoints — they have no
    duration cap. See https://docs.vidnavigator.com/guides/async-jobs.


    ## Webhooks

    Rather than polling, an async job can call you back. Pass `webhook_url` on
    the submit request, or configure an account-level default in Studio → API;
    the per-request value wins, and passing `"webhook_url": ""` opts a single
    job out of the default.


    Deliveries are signed with HMAC-SHA256 in the `X-VidNavigator-Signature`
    header (`t=<unix_ts>,v1=<hex>`, computed over `"{t}.{raw_body}"` using your
    signing secret). Delivery is at-least-once and best effort — five attempts
    backing off over ~13 minutes — so make your receiver idempotent on
    `X-VidNavigator-Delivery` and treat polling as the source of truth.


    **Auto-disable:** an account-level default endpoint that fails 20 deliveries
    in a row over more than 72 hours is switched off automatically, and the
    owner is notified in Studio. Both conditions must hold, so a busy afternoon
    of failures will not disable a healthy endpoint and neither will two
    failures a week apart; a single successful delivery resets the run. While
    disabled, jobs still run and results are still available by polling — only
    the callback stops. Re-enable it in Studio → API once the receiver is fixed.
    A per-request `webhook_url` is never auto-disabled, because it is not
    stored. Full contract: https://docs.vidnavigator.com/guides/webhooks


    ## Error Handling

    The API uses standard HTTP status codes and returns error responses in JSON
    format:

    ```json

    {
      "status": "error",
      "error": "error_type",
      "message": "Human readable error message"
    }

    ```

    Actionable errors also carry a `docs_url`. Error reference:
    https://docs.vidnavigator.com/reference/errors
  version: 1.0.0
  contact:
    name: VidNavigator Support
    url: https://vidnavigator.com/support
    email: support@vidnavigator.com
  license:
    name: Proprietary
    url: https://vidnavigator.com/terms
servers:
  - url: https://api.vidnavigator.com/v1
    description: Production server
security:
  - ApiKeyAuth: []
tags:
  - name: Transcripts
    description: Extract transcripts from online videos
  - name: TikTok
    description: Scrape TikTok profiles, and search TikTok videos and LIVE rooms by keyword
  - name: Files
    description: Manage uploaded audio/video files
  - name: Analysis
    description: AI-powered content analysis
  - name: Extraction
    description: >-
      Extract structured data from video and file transcripts using custom
      schemas
  - name: Namespaces
    description: Organize uploaded files into namespaces (folders)
  - name: Search
    description: Search videos and files using AI
  - name: System
    description: System health and information
  - name: Tweet Analysis
    description: Extract structured claims and metadata from X/Twitter tweets
  - name: Webhooks
    description: >-
      Callbacks for async jobs. Configure an account-level default endpoint and
      signing secret in Studio → API, or pass `webhook_url` per request. The
      `WebhookEvent` schema documents the payload and signature. Full contract:
      https://docs.vidnavigator.com/guides/webhooks A default endpoint that
      fails 20 deliveries in a row over more than 72 hours is disabled
      automatically and the owner notified; polling is unaffected.
paths:
  /tiktok/live/search:
    post:
      tags:
        - TikTok
      summary: Submit a TikTok LIVE search (async)
      description: >-
        Search TikTok LIVE rooms broadcasting right now for a keyword, and
        return a `task_id` immediately. Poll `GET /tiktok/live/search/{task_id}`
        for cursor-paginated results. Each room comes with its author, live
        counters (`stats.viewers`, likes, ...), `hashtags`, `category`,
        `game_tags` and, unless `include_stream_urls` is `false`, its playback
        URLs (FLV and HLS by quality, plus an audio-only stream). Results are
        retained for ~1 hour.


        Results keep TikTok's ranking and are localized to `country`. TikTok
        serves about 50 rooms per keyword; some keywords have no live room in a
        given country at a given time, which completes with zero results.


        **Billing:** 1 `residential_request` per 30 rooms TikTok returned
        (`stats.rooms_fetched`), minimum 1 per search. A keyword typically
        yields up to about 45 rooms, so 1 or 2 residential requests.


        **Usage disclosure:** This endpoint does NOT accept `include_usage`.
        Pass `include_usage=true` on `GET /tiktok/live/search/{task_id}`
        instead.
      operationId: submitTikTokLiveSearch
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - query
              properties:
                query:
                  type: string
                  minLength: 2
                  description: Keyword phrase to search LIVE rooms for.
                  example: gaming
                max_results:
                  type: integer
                  minimum: 0
                  default: 0
                  description: >-
                    Upper bound on rooms collected. `0` (the default) means as
                    many as TikTok serves, about 50 per keyword.
                country:
                  type: string
                  enum:
                    - al
                    - am
                    - ao
                    - ar
                    - at
                    - au
                    - az
                    - ba
                    - be
                    - bf
                    - bg
                    - bj
                    - bo
                    - br
                    - bw
                    - by
                    - ca
                    - cd
                    - ch
                    - ci
                    - cl
                    - cm
                    - co
                    - cr
                    - cy
                    - cz
                    - de
                    - dk
                    - do
                    - ec
                    - ee
                    - es
                    - fi
                    - fj
                    - fr
                    - gb
                    - ge
                    - gh
                    - gr
                    - gt
                    - hn
                    - hr
                    - ht
                    - hu
                    - id
                    - ie
                    - il
                    - is
                    - it
                    - jm
                    - jp
                    - ke
                    - kg
                    - kr
                    - kz
                    - lk
                    - lt
                    - lu
                    - lv
                    - md
                    - me
                    - mg
                    - mk
                    - ml
                    - mn
                    - mt
                    - mu
                    - mw
                    - mx
                    - my
                    - mz
                    - na
                    - ne
                    - ng
                    - ni
                    - nl
                    - 'no'
                    - np
                    - nz
                    - pa
                    - pe
                    - pg
                    - ph
                    - pl
                    - pr
                    - pt
                    - py
                    - ro
                    - rs
                    - rw
                    - se
                    - sg
                    - si
                    - sk
                    - sn
                    - sv
                    - tg
                    - th
                    - tj
                    - tr
                    - tt
                    - tw
                    - tz
                    - ua
                    - ug
                    - us
                    - uy
                    - uz
                    - ve
                    - vn
                    - za
                    - zm
                    - zw
                  default: us
                  example: gb
                  description: >-
                    Country whose LIVE rooms you get (ISO 3166-1 alpha-2,
                    lowercase or uppercase), one of the supported countries.
                    Default `us`.
                include_stream_urls:
                  type: boolean
                  default: true
                  description: >-
                    Return each room's playback URLs in `stream_urls` (FLV and
                    HLS by quality, plus an audio-only FLV). On by default; they
                    come at no extra cost. Pass `false` to leave them out.
                webhook_url:
                  type: string
                  format: uri
                  description: >-
                    Where to POST the result when the task finishes. Overrides
                    the account-level default configured in Studio → API; pass
                    an empty string to opt this task out of that default. Must
                    be a publicly reachable https URL. The event is a
                    notification, not the payload: it carries `stats` and tells
                    you to read the rooms from `check_status_url`. See
                    https://docs.vidnavigator.com/guides/webhooks
                  example: https://example.com/hooks/vidnavigator
      responses:
        '202':
          description: Task accepted and queued.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - success
                  data:
                    type: object
                    properties:
                      task_id:
                        type: string
                      task_status:
                        type: string
                        enum:
                          - processing
                      query:
                        type: string
                      country:
                        type: string
                        example: us
                      max_results:
                        type: integer
                      include_stream_urls:
                        type: boolean
                      expires_at:
                        type: string
                        format: date-time
                      check_status_url:
                        type: string
                        example: >-
                          /v1/tiktok/live/search/550e8400-e29b-41d4-a716-446655440000
                      message:
                        type: string
                      webhook_url:
                        type: string
                        nullable: true
                        description: The URL this task's result will be POSTed to, or null.
        '400':
          $ref: '#/components/responses/BadRequest'
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  responses:
    BadRequest:
      description: >-
        Bad request - invalid parameters. On /transcribe the `error` field may
        be `missing_parameter`, `unsupported_platform`, `unsupported_url`,
        `invalid_url`, `request_body_required`, `video_too_long`, or
        `no_videos_found` (the post carries no video).
      content:
        application/json:
          schema:
            type: object
            properties:
              status:
                type: string
                enum:
                  - error
              error:
                type: string
              message:
                type: string
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            type: object
            properties:
              status:
                type: string
                enum:
                  - error
              error:
                type: string
                enum:
                  - metadata_fetch_failed
                  - audio_extraction_failed
                  - transcription_failed
                  - internal_server_error
              message:
                type: string
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: X-API-Key
      description: >-
        API key authentication. Include your VidNavigator API key in the
        X-API-Key header.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.