openapi: 3.0.0
info:
  title: TikTok Search API
  description: |
    Search TikTok by keyword and retrieve matching profiles, videos, and photos. Use filter_by to
    scope the results to a single tab (videos, photos, or profiles) or leave it unset to get the mixed
    "all" tab. Each video and photo carries its caption, publish time, engagement counts, thumbnails,
    the sound it uses, the hashtags and mentions from the caption, and the authoring creator. Page
    through the full result set with pagination.next_page_token.
  version: 1.0.0
servers:
  - url: https://www.searchapi.io/api/v1
paths:
  /search:
    get:
      summary: TikTok Search
      security:
        - ApiKeyAuth: []
        - ApiKeyQuery: []
      parameters:
        - name: engine
          in: query
          required: true
          description: Search engine identifier
          schema:
            type: string
            enum: ["tiktok_search"]
            default: "tiktok_search"
        - name: q
          in: query
          required: false
          description: Keyword to search TikTok for (maximum 100 characters). Required unless next_page_token is given, which carries it.
          schema:
            type: string
            maxLength: 100
        - name: filter_by
          in: query
          required: false
          description: Which result tab to return. `all` mixes profiles, videos, and photos; the others return only that section.
          schema:
            type: string
            enum: ["all", "videos", "photos", "profiles"]
            default: "all"
        - name: next_page_token
          in: query
          required: false
          description: Token to retrieve the next page of results, returned as pagination.next_page_token when pagination.has_more is true. A token is issued for a specific q and filter_by; both are recovered from the token, so they can be omitted, and a conflicting value is rejected.
          schema:
            type: string
      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'
        profiles:
          type: array
          description: Matching creator profiles. Always present for filter_by `profiles`; may be present for `all` (only when the grid carries a Users card).
          items:
            $ref: '#/components/schemas/Profile'
        videos:
          type: array
          description: Matching video posts. Present for filter_by `all` and `videos`.
          items:
            $ref: '#/components/schemas/Post'
        photos:
          type: array
          description: Matching photo (image carousel) posts. Always present for filter_by `photos`; may be present for `all` (only when the grid carries photo posts). Same shape as a video item, except the link points to /photo/, duration/width/height and video_meta are absent, and each item carries carousel_items and may add a photo title.
          items:
            $ref: '#/components/schemas/Post'
        pagination:
          $ref: '#/components/schemas/Pagination'
        error:
          type: string
          description: Error message when no results are found

    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
        q:
          type: string
          description: Keyword searched for
        filter_by:
          type: string
          description: Result tab returned (all, videos, photos, or profiles)
        next_page_token:
          type: string
          description: Pagination token used for this request

    Profile:
      type: object
      properties:
        position:
          type: integer
          description: 1-based position of the profile within the profiles array
        id:
          type: string
          description: TikTok numeric user ID
        sec_uid:
          type: string
          description: TikTok secure user ID (secUid), the opaque key TikTok's own user and post endpoints require
        username:
          type: string
          description: TikTok username
        name:
          type: string
          description: Display name
        link:
          type: string
          description: URL to the profile page
        bio:
          type: string
          description: Profile bio or description
        avatar:
          type: string
          description: URL to the profile avatar thumbnail (100x100 webp, signed by TikTok, expires after ~24 hours)
        is_verified:
          type: boolean
          description: Present and true when the account is verified
        followers:
          type: integer
          description: Number of followers
        hearts:
          type: integer
          description: Total hearts (likes) received across all videos

    Post:
      type: object
      properties:
        position:
          type: integer
          description: 1-based position of the post within its section (videos or photos)
        grid_position:
          type: integer
          description: 1-based rank of the post in TikTok's mixed all-tab results grid, which interleaves videos and photos (filter_by=all only). A single rank, not a row/column. Absent on the single-filter tabs.
        id:
          type: string
          description: TikTok post ID
        caption:
          type: string
          description: Post caption
        language:
          type: string
          description: Caption language code (e.g. en, es)
        link:
          type: string
          description: Canonical URL to the post (/video/ for videos, /photo/ for image carousels)
        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)
        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: Present and true when the post is a sponsored/promoted result
        is_pinned:
          type: boolean
          description: Present and true when the post is pinned to its author's profile
        is_duet_enabled:
          type: boolean
          description: Present and true when duets are allowed on the video
        is_stitch_enabled:
          type: boolean
          description: Present and true when stitches are allowed on the video
        views:
          type: integer
          description: Number of views (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)
        thumbnail:
          type: string
          description: Cover image URL (signed by TikTok, expires after ~48 hours)
        dynamic_thumbnail:
          type: string
          description: Animated cover image URL (signed by TikTok, expires after ~48 hours; absent for photo posts)
        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'
        video_meta:
          $ref: '#/components/schemas/VideoMeta'
        music:
          $ref: '#/components/schemas/Music'
        location:
          $ref: '#/components/schemas/Location'
        subtitles:
          type: array
          description: Available closed captions (absent when the video has none)
          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:
          $ref: '#/components/schemas/Author'

    Author:
      type: object
      description: The creator who posted the video or photo
      properties:
        id:
          type: string
          description: TikTok numeric user ID
        sec_uid:
          type: string
          description: TikTok secure user ID (secUid), the opaque key TikTok's own user and post endpoints require
        username:
          type: string
          description: TikTok username
        link:
          type: string
          description: URL of the creator's profile
        name:
          type: string
          description: Display name
        bio:
          type: string
          description: Profile bio or description
        avatar:
          type: string
          description: URL to the author's avatar image (720x720, or the 100x100 thumbnail when TikTok omits it; signed by TikTok, expires after ~48 hours)
        avatar_hd:
          type: string
          description: URL to the author's 1080x1080 avatar image (signed separately by TikTok, expires after ~48 hours)
        is_verified:
          type: boolean
          description: Present and true when the author is verified
        is_private:
          type: boolean
          description: Present and true when the account is private
        followers:
          type: integer
          description: Author's follower count
        following:
          type: integer
          description: Number of accounts the author follows
        hearts:
          type: integer
          description: Total hearts (likes) received across all posts
        posts:
          type: integer
          description: Total number of posts

    Location:
      type: object
      description: Venue tagged on the post (absent when the post has no place tag)
      properties:
        id:
          type: string
          description: TikTok place ID
        name:
          type: string
          description: Venue name
        address:
          type: string
          description: Street address
        city:
          type: string
          description: City
        category:
          type: string
          description: Venue category (e.g. Food and Drink)

    Music:
      type: object
      properties:
        id:
          type: string
          description: TikTok sound ID
        title:
          type: string
          description: Sound title
        album:
          type: string
          description: Album the sound belongs to (absent for original sounds; can differ from the title)
        author:
          type: string
          description: Sound author name
        cover:
          type: string
          description: Sound cover art URL (signed by TikTok, expires after ~48 hours)
        duration:
          type: integer
          description: Sound duration in seconds
        play_url:
          type: string
          description: Direct audio stream URL (signed by TikTok, expires)
        is_original:
          type: boolean
          description: Present and true when the sound is an original creation
        is_copyrighted:
          type: boolean
          description: Present and true when the sound is copyrighted
        link:
          type: string
          description: URL to the sound's TikTok page

    VideoMeta:
      type: object
      description: Video quality and encoding metadata (absent for photo posts)
      properties:
        definition:
          type: string
          description: Playback definition label (e.g. 540p, 720p)
        ratio:
          type: string
          description: Aspect/quality ratio label
        format:
          type: string
          description: Container format (e.g. mp4)
        codec_type:
          type: string
          description: Video codec (e.g. h264)
        size:
          type: integer
          description: Encoded size in bytes of the default rendition
        bitrate:
          type: integer
          description: Bitrate in bits per second of the default rendition
        bitrates:
          type: array
          description: Per-codec encoding variants
          items:
            $ref: '#/components/schemas/Bitrate'

    Bitrate:
      type: object
      properties:
        gear_name:
          type: string
          description: TikTok internal rendition name
        bitrate:
          type: integer
          description: Bitrate in bits per second
        codec_type:
          type: string
          description: Video codec (e.g. h264, h265_hvc1)

    Subtitle:
      type: object
      properties:
        language:
          type: string
          description: Caption language code (e.g. eng-US)
        format:
          type: string
          description: Caption file format (e.g. webvtt)
        source:
          type: string
          description: How the caption was produced (e.g. ASR for auto-generated)
        url:
          type: string
          description: Caption file URL (signed by TikTok, expires)
        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

    Pagination:
      type: object
      properties:
        has_more:
          type: boolean
          description: Present and true when more results are available on a following page
        is_last_page:
          type: boolean
          description: Present and true when this is the final page of results
        next_page_token:
          type: string
          description: Token to pass back as next_page_token to retrieve the next page of results

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