openapi: 3.0.0
info:
  title: TikTok Video API
  description: |
    Retrieve structured data for a single TikTok video (or photo carousel) from its URL. The response
    includes the caption, publish time, duration, thumbnails, engagement counts, encoding metadata,
    subtitle tracks, the sound it uses, and the hashtags and mentions parsed from the caption, along
    with the author's profile details. Photo carousels also include the full-resolution slide images.
  version: 1.0.0
servers:
  - url: https://www.searchapi.io/api/v1
paths:
  /search:
    get:
      summary: TikTok Video Search
      security:
        - ApiKeyAuth: []
        - ApiKeyQuery: []
      parameters:
        - name: engine
          in: query
          required: true
          description: Search engine identifier
          schema:
            type: string
            enum: ["tiktok_video"]
            default: "tiktok_video"
        - name: url
          in: query
          required: false
          description: >-
            Full TikTok video URL (e.g. https://www.tiktok.com/@spidermanmovie/video/7670979152308079885).
            Photo carousel (/photo/) and short vm./vt.tiktok.com and tiktok.com/t/ links are also accepted,
            except short links pointing to photo posts; pass the full /photo/ URL for those. Required if
            video_id and username are not provided; cannot be combined with them.
          schema:
            type: string
        - name: video_id
          in: query
          required: false
          description: Numeric TikTok video ID. Alternative to url; must be paired with username.
          schema:
            type: string
            pattern: '^\d+$'
        - name: username
          in: query
          required: false
          description: TikTok creator username (with or without the @ symbol). Alternative to url; must be paired with video_id.
          schema:
            type: string
            pattern: '^@?[a-zA-Z0-9_.]{1,24}$'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SearchResponse'
        '400':
          description: Validation Error. There is an issue with query parameters, such as missing required parameters or invalid values.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '401':
          description: Authentication Error. The API key is missing or invalid.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '429':
          description: Rate Limit Exceeded. The number of allowed requests has been exceeded. Consider upgrading your plan or waiting for the limit to reset.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '500':
          description: Server Error. Internal server error.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
        '503':
          description: Timeout. We could not retrieve results in 90 seconds.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/ErrorResponse'
components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      in: header
      name: Authorization
      description: 'Use Bearer authentication. Format: "Bearer YOUR_API_KEY"'
    ApiKeyQuery:
      type: apiKey
      in: query
      name: api_key
      description: Pass API key as query parameter
  schemas:
    SearchResponse:
      type: object
      properties:
        search_metadata:
          $ref: '#/components/schemas/SearchMetadata'
        search_parameters:
          $ref: '#/components/schemas/SearchParameters'
        video:
          $ref: '#/components/schemas/Video'
        author:
          $ref: '#/components/schemas/Author'
        error:
          type: string
          description: Error message when the video cannot be returned (not found, private, or region locked)

    SearchMetadata:
      type: object
      required: [id, status, created_at]
      properties:
        id:
          type: string
          description: Unique identifier for the search request
        status:
          type: string
          description: Status of the search request
        created_at:
          type: string
          format: date-time
          description: Timestamp when the search was created
        request_time_taken:
          type: number
          description: Time taken to make the request in seconds
        parsing_time_taken:
          type: number
          description: Time taken to parse the results in seconds
        total_time_taken:
          type: number
          description: Total time taken for the search in seconds
        request_url:
          type: string
          description: TikTok URL for this search
        html_url:
          type: string
          description: URL to view HTML results
        json_url:
          type: string
          description: URL to view JSON results

    SearchParameters:
      type: object
      properties:
        engine:
          type: string
          description: Search engine identifier
        url:
          type: string
          description: TikTok video URL requested
        video_id:
          type: string
          description: TikTok video ID requested
        username:
          type: string
          description: TikTok username requested

    Video:
      type: object
      properties:
        id:
          type: string
          description: TikTok video ID
        link:
          type: string
          description: Canonical URL to the video (or /photo/ for image carousels)
        caption:
          type: string
          description: Video caption
        language:
          type: string
          description: Language code of the caption text
        iso_date:
          type: string
          format: date-time
          description: Publish time in ISO 8601 format
        duration:
          type: integer
          description: Video duration in seconds (absent for photo posts)
        width:
          type: integer
          description: Video width in pixels (absent for photo posts)
        height:
          type: integer
          description: Video height in pixels (absent for photo posts)
        is_ad:
          type: boolean
          description: Whether the video is an ad
        is_duet_enabled:
          type: boolean
          description: Whether duets are allowed for this video
        is_stitch_enabled:
          type: boolean
          description: Whether stitches are allowed for this video
        thumbnail:
          type: string
          description: Cover image URL
        dynamic_thumbnail:
          type: string
          description: Animated cover image URL
        type:
          type: string
          enum: [video, photo, carousel]
          description: Post type; photo is a single-image post, carousel a multi-image post (both use /photo/ links)
        title:
          type: string
          description: Photo post title, separate from the caption (photo carousels only)
        carousel_items:
          type: array
          description: Carousel slides (photo carousels only)
          items:
            $ref: '#/components/schemas/CarouselItem'
        views:
          type: integer
          description: Number of plays
        likes:
          type: integer
          description: Number of likes (diggs)
        comments:
          type: integer
          description: Number of comments
        shares:
          type: integer
          description: Number of shares
        saves:
          type: integer
          description: Number of saves (collects)
        video_meta:
          $ref: '#/components/schemas/VideoMeta'
        music:
          $ref: '#/components/schemas/Music'
        subtitles:
          type: array
          description: Subtitle tracks available for the video
          items:
            $ref: '#/components/schemas/Subtitle'
        hashtags:
          type: array
          description: Hashtags parsed from the caption
          items:
            type: string
        mentions:
          type: array
          description: Usernames mentioned in the caption
          items:
            type: string

    Author:
      type: object
      properties:
        id:
          type: string
          description: TikTok numeric user ID
        username:
          type: string
          description: TikTok username
        name:
          type: string
          description: Display name
        bio:
          type: string
          description: Profile bio or description
        avatar:
          type: string
          description: URL to the profile avatar image
        is_verified:
          type: boolean
          description: Whether the account is verified
        is_private:
          type: boolean
          description: Whether the account is private
        followers:
          type: integer
          description: Number of followers
        following:
          type: integer
          description: Number of accounts being followed
        hearts:
          type: integer
          description: Total hearts (likes) received across all videos
        posts:
          type: integer
          description: Total number of videos posted

    VideoMeta:
      type: object
      properties:
        definition:
          type: string
          description: Playback quality of the default rendition
        ratio:
          type: string
          description: Resolution label of the default rendition
        format:
          type: string
          description: Container format
        codec_type:
          type: string
          description: Video codec
        size:
          type: integer
          description: File size in bytes
        bitrate:
          type: integer
          description: Bitrate of the default rendition in bits per second
        bitrates:
          type: array
          description: Available encoding variants
          items:
            $ref: '#/components/schemas/Bitrate'

    Bitrate:
      type: object
      properties:
        gear_name:
          type: string
          description: Internal name of the encoding variant
        bitrate:
          type: integer
          description: Bitrate in bits per second
        fps:
          type: integer
          description: Frames per second
        codec_type:
          type: string
          description: Video codec
        format:
          type: string
          description: Container format

    Music:
      type: object
      properties:
        id:
          type: string
          description: TikTok sound ID
        title:
          type: string
          description: Sound title
        author:
          type: string
          description: Sound author name
        cover:
          type: string
          description: Sound cover image URL
        duration:
          type: integer
          description: Sound duration in seconds
        play_url:
          type: string
          description: Direct audio playback URL
        is_original:
          type: boolean
          description: Whether the sound is an original sound
        is_copyrighted:
          type: boolean
          description: Whether the sound is copyrighted
        link:
          type: string
          description: URL to the sound's TikTok page

    Subtitle:
      type: object
      properties:
        language:
          type: string
          description: Caption language code with region (e.g. eng-US)
        format:
          type: string
          description: Subtitle file format
        source:
          type: string
          description: 'How the captions were produced (e.g. ASR: automatic speech recognition)'
        url:
          type: string
          description: URL to the subtitle file
        url_expires_at:
          type: string
          format: date-time
          description: UTC ISO 8601 timestamp when the subtitle url expires

    CarouselItem:
      type: object
      properties:
        position:
          type: integer
          description: 1-based slide position
        image:
          type: string
          description: Full-resolution slide image URL
        width:
          type: integer
          description: Slide image width in pixels
        height:
          type: integer
          description: Slide image height in pixels

    ErrorResponse:
      type: object
      required: [error]
      properties:
        error:
          type: string
          description: Error message describing what went wrong
