> ## 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.

# Get TikTok Profile Scrape Result

> Poll an async TikTok profile scrape task and retrieve a cursor-paginated page of videos.

**Cursor pagination:** The cursor encodes an absolute offset, so it is safe to change `limit` between calls without skipping or duplicating videos. Pass the `next_cursor` returned from a previous response as `cursor` in the next request. Omit `cursor` to start from the beginning.

**TTL:** Tasks (and their `download_url` availability) expire ~1 hour after creation. Poll while `task_status` is `processing`, and switch to `download_url` for very large profiles.

This endpoint does not consume credits — polling is free.

**Usage disclosure:** Set `include_usage=true` to receive a `usage` block describing the charges the background worker recorded for this task. Returned only when `task_status=completed` (processing tasks haven't finished billing; failed tasks have all charges refunded). Charges are `standard_request` units, one per TikTok page consumed.

Poll a TikTok profile scrape task and retrieve cursor-paginated videos once the background job finishes.

## Overview

This endpoint is the second half of the TikTok profile scraping workflow. Use it after you submit a scrape with [`POST /tiktok/profile`](/api-reference/endpoint/tiktok-profile).

It serves three purposes:

* check whether the task is still running
* retrieve the filtered video results page by page
* get a temporary `download_url` for the full JSON result when available

This endpoint does **not** consume credits.

## Request Parameters

| Parameter | In    | Required | Description                                                                 |
| --------- | ----- | -------- | --------------------------------------------------------------------------- |
| `task_id` | path  | Yes      | Task ID returned by `POST /tiktok/profile`                                  |
| `cursor`  | query | No       | Opaque pagination cursor from a previous response                           |
| `limit`   | query | No       | Maximum number of videos to return, between `1` and `500`. Default is `50`. |

## How Pagination Works

Pagination is cursor-based, but the cursor encodes an absolute offset. That means you can safely change `limit` between requests without skipping or duplicating videos.

Typical flow:

1. Call the endpoint with no `cursor`.
2. Read `data.pagination.next_cursor`.
3. Pass that value back as the next request's `cursor`.
4. Stop when `has_next` is `false`.

## Polling Lifecycle

The `task_status` field will be one of:

* `processing`: the scrape is still running
* `completed`: the scrape finished and results are ready
* `failed`: the scrape ended with an error

While the task is still processing:

* `profile` may be `null`
* `videos` will be empty
* `download_url` will usually be `null`

Once completed:

* `videos` contains a cursor-paginated page of matching posts
* `pagination` tells you whether more pages exist
* `download_url` may contain a temporary signed URL for the full JSON result

## Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl "https://api.vidnavigator.com/v1/tiktok/profile/tt_profile_abc123?limit=25" \
    -H "X-API-Key: YOUR_API_KEY"
  ```

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

  response = requests.get(
      "https://api.vidnavigator.com/v1/tiktok/profile/tt_profile_abc123",
      headers={"X-API-Key": "YOUR_API_KEY"},
      params={"limit": 25},
  )

  print(response.json())
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch(
    'https://api.vidnavigator.com/v1/tiktok/profile/tt_profile_abc123?limit=25',
    {
      headers: {
        'X-API-Key': 'YOUR_API_KEY'
      }
    }
  );

  const result = await response.json();
  ```
</CodeGroup>

### Fetch the Next Page

```bash cURL theme={null}
curl "https://api.vidnavigator.com/v1/tiktok/profile/tt_profile_abc123?limit=25&cursor=eyJvZmZzZXQiOjI1fQ==" \
  -H "X-API-Key: YOUR_API_KEY"
```

## Example Completed Response

```json theme={null}
{
  "status": "success",
  "data": {
    "task_id": "tt_profile_abc123",
    "task_status": "completed",
    "profile_url": "https://www.tiktok.com/@tiktok",
    "profile": {
      "uploader": "tiktok",
      "follower_count": 12345678
    },
    "filters": {
      "max_posts": 50,
      "after_datetime": "2024-01-01T00:00:00Z",
      "before_datetime": null,
      "min_likes": 10000,
      "max_likes": null
    },
    "stats": {
      "videos_scanned": 120,
      "videos_matched": 50,
      "pages_consumed": 8
    },
    "videos": [
      {
        "id": "7351234567890123456",
        "track": "Original sound",
        "artists": ["Creator Name"],
        "duration": 28,
        "title": "Example TikTok",
        "description": "Video caption text here",
        "timestamp": 1712345678,
        "published_at": "2024-04-05T19:34:38Z",
        "views": 250000,
        "likes": 22000,
        "reposts": 180,
        "comments": 950,
        "thumbnails": [],
        "url": "https://www.tiktok.com/@tiktok/video/7351234567890123456"
      }
    ],
    "pagination": {
      "limit": 25,
      "offset": 0,
      "total_items": 50,
      "has_next": true,
      "has_prev": false,
      "next_cursor": "eyJvZmZzZXQiOjI1fQ==",
      "prev_cursor": null
    },
    "download_url": "https://storage.googleapis.com/bucket/api/tiktok_profiles/user/task.json?...",
    "error_message": null,
    "created_at": "2026-04-25T20:00:00Z",
    "completed_at": "2026-04-25T20:01:12Z",
    "expires_at": "2026-04-25T21:00:00Z"
  }
}
```

## Understanding the Response

### `profile`

Contains profile-level metadata returned by the scraper, such as uploader information and follower counts when available.

### `stats`

Helps you understand what happened during the scrape:

* `videos_scanned`: total TikTok entries iterated before filtering
* `videos_matched`: entries that passed your filters
* `pages_consumed`: estimated number of TikTok API pages fetched during the scrape

### `videos`

This is the current page of matched TikTok videos. Each item includes public metadata such as:

* `id`
* `title`
* `description`
* `timestamp`: Unix timestamp in seconds when the video was uploaded
* `published_at`: UTC datetime string derived from `timestamp`, in ISO 8601 format with timezone
* `views`
* `likes`
* `comments`
* `url`

### `download_url`

When present, this is a short-lived signed URL pointing to the full scrape result as one JSON file. It is useful for large profiles, browser downloads, and no-code integrations.

If it is `null`, either:

* the task has not finished yet, or
* signed URL generation is not configured and you should paginate through `videos` instead

## Error Cases

* `400 invalid_cursor`: the supplied `cursor` is invalid
* `404 task_not_found`: task does not exist, expired, or does not belong to the current user

## Tips

* poll every few seconds while `task_status` is `processing`
* switch to `download_url` for large completed jobs
* do not assume tasks live forever; they expire after about 1 hour
* call the endpoint again later if you need a freshly minted `download_url`
* use the `expires_at` value to avoid polling a task after it has already expired


## OpenAPI

````yaml GET /tiktok/profile/{task_id}
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.


    ## 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"
    }

    ```
  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 profile metadata and per-video stats
  - 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
paths:
  /tiktok/profile/{task_id}:
    get:
      tags:
        - TikTok
      summary: Get TikTok profile scrape result
      description: >-
        Poll an async TikTok profile scrape task and retrieve a cursor-paginated
        page of videos.


        **Cursor pagination:** The cursor encodes an absolute offset, so it is
        safe to change `limit` between calls without skipping or duplicating
        videos. Pass the `next_cursor` returned from a previous response as
        `cursor` in the next request. Omit `cursor` to start from the beginning.


        **TTL:** Tasks (and their `download_url` availability) expire ~1 hour
        after creation. Poll while `task_status` is `processing`, and switch to
        `download_url` for very large profiles.


        This endpoint does not consume credits — polling is free.


        **Usage disclosure:** Set `include_usage=true` to receive a `usage`
        block describing the charges the background worker recorded for this
        task. Returned only when `task_status=completed` (processing tasks
        haven't finished billing; failed tasks have all charges refunded).
        Charges are `standard_request` units, one per TikTok page consumed.
      operationId: getTikTokProfileScrape
      parameters:
        - name: task_id
          in: path
          required: true
          description: ID returned by POST /tiktok/profile.
          schema:
            type: string
        - name: cursor
          in: query
          required: false
          description: >-
            Opaque pagination cursor returned as `next_cursor` from the previous
            response. Omit to fetch the first page.
          schema:
            type: string
        - name: limit
          in: query
          required: false
          description: Maximum number of videos to include in the response.
          schema:
            type: integer
            minimum: 1
            maximum: 500
            default: 50
        - name: include_usage
          in: query
          required: false
          description: >-
            When true and `task_status=completed`, attach a `usage` block
            describing the charges the background worker recorded
            (`standard_request` × `pages_consumed`).
          schema:
            type: boolean
            default: false
      responses:
        '200':
          description: >-
            Task found. `task_status` may be `processing`, `completed`, or
            `failed`.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - success
                  data:
                    $ref: '#/components/schemas/TikTokProfileTask'
        '400':
          description: Invalid cursor.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - error
                  error:
                    type: string
                    enum:
                      - invalid_cursor
                  message:
                    type: string
        '404':
          description: Task not found, expired (>1h), or not owned by this user.
          content:
            application/json:
              schema:
                type: object
                properties:
                  status:
                    type: string
                    enum:
                      - error
                  error:
                    type: string
                    enum:
                      - task_not_found
                  message:
                    type: string
        '500':
          $ref: '#/components/responses/InternalServerError'
components:
  schemas:
    TikTokProfileTask:
      type: object
      description: >-
        TikTok profile scrape task result body returned by GET
        /tiktok/profile/{task_id}.
      properties:
        task_id:
          type: string
        task_status:
          type: string
          enum:
            - processing
            - completed
            - failed
        profile_url:
          type: string
          format: uri
        profile:
          type: object
          nullable: true
          additionalProperties: true
          description: >-
            Profile metadata (uploader, follower count, etc.). Null while task
            is still processing.
        filters:
          $ref: '#/components/schemas/TikTokProfileFilters'
        stats:
          $ref: '#/components/schemas/TikTokProfileStats'
        videos:
          type: array
          items:
            $ref: '#/components/schemas/TikTokVideo'
          description: >-
            Page of videos according to cursor/limit. Empty while task_status !=
            completed.
        pagination:
          $ref: '#/components/schemas/TikTokProfilePagination'
        download_url:
          type: string
          format: uri
          nullable: true
          description: >-
            Short-lived (~1 hour) signed Google Cloud Storage URL with the full
            scrape result as a single JSON file. Same model as AWS S3 /
            CloudFront pre-signed URLs: time-limited and resource-scoped, so it
            can be used from browsers, no-code tools, or any HTTP client without
            forwarding header auth. Set for completed tasks when GCS is
            configured; otherwise null and clients must paginate. Call GET
            /tiktok/profile/{task_id} again at any time to mint a fresh URL.
          example: >-
            https://storage.googleapis.com/bucket/api/tiktok_profiles/user/task.json?X-Goog-Algorithm=GOOG4-RSA-SHA256&X-Goog-Signature=...
        error_message:
          type: string
          nullable: true
          description: Present only when task_status is 'failed'.
        created_at:
          type: string
          format: date-time
          nullable: true
        completed_at:
          type: string
          format: date-time
          nullable: true
        expires_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            When the task document and its download URL availability expire (~1
            hour after creation).
    TikTokProfileFilters:
      type: object
      description: Echo of input filters for the scrape, useful for debugging.
      properties:
        max_posts:
          type: integer
          nullable: true
        after_datetime:
          type: string
          nullable: true
          description: YYYY-MM-DD or ISO datetime with timezone
        before_datetime:
          type: string
          nullable: true
          description: YYYY-MM-DD or ISO datetime with timezone
        min_likes:
          type: integer
          nullable: true
        max_likes:
          type: integer
          nullable: true
    TikTokProfileStats:
      type: object
      properties:
        videos_scanned:
          type: integer
          description: Total entries iterated from TikTok before filtering
        videos_matched:
          type: integer
          description: Entries that passed all filters and made it into the result
        pages_consumed:
          type: integer
          description: >-
            Estimated number of TikTok API pages fetched. Charged 1:1 as
            transcript retrievals.
    TikTokVideo:
      type: object
      description: >-
        Public metadata for a single TikTok video returned by the profile
        scraper.
      properties:
        id:
          type: string
          description: TikTok video ID
        track:
          type: string
          nullable: true
          description: Audio track / sound title
        artists:
          type: array
          items:
            type: string
          description: Artist or creator names associated with the audio
        duration:
          type: integer
          nullable: true
          description: Video length in seconds
        title:
          type: string
          nullable: true
        description:
          type: string
          nullable: true
        timestamp:
          type: integer
          nullable: true
          description: Unix timestamp (seconds) when the video was uploaded
        published_at:
          type: string
          format: date-time
          nullable: true
          description: >-
            UTC datetime string derived from `timestamp` (ISO 8601 with
            timezone).
        views:
          type: integer
          nullable: true
        likes:
          type: integer
          nullable: true
        reposts:
          type: integer
          nullable: true
        comments:
          type: integer
          nullable: true
        thumbnails:
          type: array
          items:
            type: object
            additionalProperties: true
        url:
          type: string
          format: uri
    TikTokProfilePagination:
      type: object
      description: >-
        Cursor-based pagination over the videos array. The cursor encodes an
        absolute offset, so callers can change `limit` between requests without
        skipping or duplicating items.
      properties:
        limit:
          type: integer
        offset:
          type: integer
        total_items:
          type: integer
        has_next:
          type: boolean
        has_prev:
          type: boolean
        next_cursor:
          type: string
          nullable: true
          description: >-
            Opaque cursor; pass in `cursor` query param of the next request, or
            null when has_next is false.
        prev_cursor:
          type: string
          nullable: true
  responses:
    InternalServerError:
      description: Internal server error
      content:
        application/json:
          schema:
            type: object
            properties:
              status:
                type: string
                enum:
                  - error
              error:
                type: string
                enum:
                  - 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.

````