---
title: "TikTok Audience Demographics API"
method: GET
path: "/v1/tiktok/audience-demographics"
tags: ["TikTok"]
---

# TikTok Audience Demographics API

`GET /v1/tiktok/audience-demographics`

## Request

- Base URL: `https://api.captapi.com`
- URL: `https://api.captapi.com/v1/tiktok/audience-demographics`
- Auth: one of:
  - HTTP bearer
  - API key in header `X-API-Key`

Audience country + language mix for a TikTok creator — engagement sample, not a follower census.

Give a profile URL, @handle, or username and get a ranked audience-country breakdown as clean JSON. TikTok does not publish follower geography — we sample people engaging with recent videos. The two signals come from two populations, disclosed in the response: audienceLanguages[] are tallied from top-level commenters (basis.language="commenters"), while audienceLocations[] come from repliers under the most-replied parent comments (basis.region="repliers") — the only public surface that reliably exposes user.region. Each country row carries country name, countryCode, count, and numeric percentage (+ percentageText). Response includes sampleSize, totalCountries, regionSampleParents + regionSampleVideos (how many distinct parent threads / videos the region sample is spread over), and a clustering-aware confidence: the size-based label (low <400, medium 400–999, high ≥1000) is CAPPED when the region sample is concentrated in few threads (<8 parents or <4 videos → low; <20 parents or <8 videos → at most medium), because 400 repliers from 6 threads are not 400 independent observations. Optional other{} only when countriesLimit truncates. timings{path,postsVia,postsMs,postsDeadlineMs,commentsMs,commentsVia,totalMs,videoConcurrency,commentsAttempts,commentsErrors,commentsAttemptsPerVideo} — postsVia names the leg that served the video list (native), commentsVia the comments surface (web+replies), commentsErrors counts blocked comment requests absorbed before clean pages, and commentsAttemptsPerVideo is the per-video attempts distribution (sorted desc). If the posts leg hits its deadline on a real profile you get a degraded 200 (degraded:true, degradedReason:"posts-timeout", 0 credits) — 404 NOT_FOUND is reserved for profiles positively confirmed absent, never for a slow fetch. Choose videos=12|30|60 (credits 3/5/8) for sample depth. Percentages across audienceLocations (+ other) sum to ~100%. This reflects who engages, not a full follower census.

Docs: https://captapi.com/apis/tiktok-audience-demographics

## Query parameters

- `url` string, required
- `videos` integer
- `countriesLimit` integer
- `cache` boolean

## Response `200`

Success. The data object for this endpoint.

- object
  - `success` unknown, required
  - `data` object, required
    - `platform` string: Platform identifier for this response (matches the endpoint's platform).
    - `username` string: Account username / handle.
    - `url` string: Canonical URL of the item.
    - `videosSampled` integer: How many of the creator's recent videos were sampled to build the breakdown.
    - `sampleSize` integer: Total number of commenter countries counted across the sampled videos.
    - `audienceLocations` object[]
      - `country` string: Country for the request context. On popular-creators top-level: ISO feed market you queried (e.g. US) — not each creator's home country (see region).
      - `countryCode` string: ISO-3166 alpha-2 country code (e.g. US, MX).
      - `count` integer: Number of items in this bucket (e.g. commenters from this country in the sample).
      - `percentage` number: Numeric share of the sample (e.g. 26.02). Never a string — use percentageText for display. Values across audienceLocations (+ other) sum to ~100.
      - `percentageText` string: Display form of percentage with a % suffix (e.g. "26.02%"). Prefer percentage for math.
    - `basis` object
      - `language` string: Detected or requested language code.
      - `region` string: Region or country code for this result (meaning depends on the endpoint — market vs creator home).
    - `videosRequested` integer: videos query parameter used for this call (12, 30, or 60).
    - `totalCountries` integer: How many distinct countries appeared in the commenter sample (before countriesLimit truncation).
    - `confidence` string: Sample-strength from sampleSize ("low" <400, "medium" 400–999, "high" ≥1000), capped for clustering: regionSampleParents <8 or regionSampleVideos <4 forces low; <20 parents or <8 videos caps at medium.
    - `other` object
      - `count` integer: Number of items in this bucket (e.g. commenters from this country in the sample).
      - `percentage` number: Numeric share of the sample (e.g. 26.02). Never a string — use percentageText for display. Values across audienceLocations (+ other) sum to ~100.
      - `percentageText` string: Display form of percentage with a % suffix (e.g. "26.02%"). Prefer percentage for math.
    - `audienceLanguages` object[]
      - `language` string: Detected or requested language code.
      - `count` integer: Number of items in this bucket (e.g. commenters from this country in the sample).
      - `percentage` number: Numeric share of the sample (e.g. 26.02). Never a string — use percentageText for display. Values across audienceLocations (+ other) sum to ~100.
      - `percentageText` string: Display form of percentage with a % suffix (e.g. "26.02%"). Prefer percentage for math.
    - `languageSampleSize` integer: How many comments contributed a language code to audienceLanguages.
    - `regionSampleParents` integer: Distinct parent comment threads the region sample is spread over. Low values mean repliers clustered in few conversations — confidence is capped accordingly.
    - `regionSampleVideos` integer: Distinct videos that contributed at least one replier to the region sample.

## Other responses

- `400`: Bad request: wrong platform URL, unknown endpoint, or an invalid parameter value. Not billed.
- `401`: Missing, invalid or revoked API key. Not billed.
- `402`: Not enough credits for this request. Not billed.
- `404`: The resource does not exist or is not public. Not billed.
- `422`: A required parameter is missing or has the wrong type. Not billed.
- `429`: Rate limit reached. Wait for Retry-After seconds. Not billed.
- `502`: The platform could not be reached or returned nothing usable. Retryable, not billed. 503 and 504 use the same envelope.

---

[API](https://skmtc.dev/captapi/apis/captapi-api.md) · [All operations](https://skmtc.dev/captapi/apis/captapi-api/llms.txt) · [OpenAPI document](https://skmtc.dev/captapi/apis/captapi-api/revisions/c9b9ac5ff1bd?raw)
