# GET /v1/profile

The creator behind the posts — one shape across TikTok, Instagram, YouTube and X. Pass a profile URL, or a bare handle with `platform`.

## Request

```bash
curl "https://tikdata.io/v1/profile?url=https://www.tiktok.com/@tiktok" \
  -H "Authorization: Bearer thr_live_xxx"
```

```bash
curl "https://tikdata.io/v1/profile?handle=nasa&platform=x" \
  -H "Authorization: Bearer thr_live_xxx"
```

| param | required | notes |
|---|---|---|
| `url` | one of `url` or `handle` | a profile URL — `tiktok.com/@user`, `instagram.com/user`, `youtube.com/@user` or `/channel/UC…`, `x.com/user` |
| `handle` | one of `url` or `handle` | bare handle; needs `platform` |
| `platform` | with `handle` | `tiktok` \| `instagram` \| `youtube` \| `x` |

A **post** URL sent here is rejected with a hint pointing at [`/v1/post`](/docs/post.md).

## Response — 200

```json
{
  "platform": "tiktok",
  "id": "107955",
  "handle": "tiktok",
  "url": "https://www.tiktok.com/@tiktok",
  "name": "TikTok",
  "bio": "One TikTok can make a big impact",
  "avatar": "https://p16-common-sign.tiktokcdn-us.com/…",
  "verified": true,
  "private": false,
  "createdAt": null,
  "stats": {
    "followers": 95632564,
    "following": 1,
    "posts": 1583,
    "likes": 463326549,
    "views": 0
  }
}
```

| field | type | notes |
|---|---|---|
| `id` | string | platform's own account id (X: `rest_id`; YouTube: `UC…` channel id) |
| `handle` | string | bare, no `@` |
| `url` | string | canonical profile URL |
| `name` `bio` `avatar` | string | `""` if absent |
| `verified` | boolean | TikTok: enterprise verification or badge; X: blue check; Instagram/YouTube: the platform flag |
| `private` | boolean | TikTok/Instagram private account; X protected |
| `createdAt` | ISO 8601 \| null | X and YouTube only |
| `stats.followers` | integer | subscribers on YouTube |
| `stats.following` | integer | `0` on YouTube |
| `stats.posts` | integer | videos on YouTube, tweets on X |
| `stats.likes` | integer | TikTok lifetime likes received; `0` elsewhere |
| `stats.views` | integer | YouTube lifetime channel views; `0` elsewhere |

## Verified live, per platform

| | followers | posts | extra |
|---|---|---|---|
| TikTok @tiktok | 95,632,564 | 1,583 | 463M lifetime likes |
| X @nasa | 92,385,909 | 74,276 | 117 following |
| Instagram @instagram | 686,452,333 | 8,579 | |
| YouTube @RickAstleyYT | 4,540,000 | 435 | 2.56B channel views |

### Per-platform notes

- **X** reports followers as `sub_count`. `followers_count` does not exist on that endpoint — the obvious key reads 0.
- **X and Instagram answer HTTP 200 for accounts that do not exist** — X with `status: "notfound"`, Instagram with `status: false` and an `errorMessage`. Both become **404** here; without that check, a creator who *renamed* would record as one who lost their whole audience.
- **Instagram's not-found is sometimes a lie.** About 1 in 4 calls returns "This account does not exist." for accounts that exist. TikData retries that response once (≈600 ms later) before believing it; a genuine not-found is still a 404. See [errors](/docs/errors.md).
- **TikTok**'s endpoint accepts `sec_user_id` as well as `unique_id`, but a handle sent as `sec_user_id` answers 200 with an empty body rather than an error. Always `unique_id`.
- **YouTube** needs a channel id, so an `@handle` costs **one extra call** to resolve (`get_channel_id`, which takes `channel_name`). A `/channel/UC…` URL skips it. Subscriber count is parsed from a display string (`"4.54M subscribers"`).

## Errors

| status | body |
|---|---|
| 400 | `{"error":"url is required","hint":"GET /v1/profile?url=https://www.tiktok.com/@tiktok"}` |
| 400 | `{"error":"unknown platform","hint":"supported: tiktok, instagram, youtube, x"}` |
| 400 | `{"error":"unrecognized url","hint":"pass a profile url, or ?handle=<name>&platform=…"}` |
| 400 | `{"error":"could not extract a tiktok handle from that url","hint":"this looks like a post url — use /v1/post for a single post"}` |
| 404 | `{"error":"profile not found","platform":"x","handle":"…"}` |
| 502 | `{"error":"upstream unreachable"}` or `{"error":"upstream error", …}` |

## Billing

One upstream call (two for a YouTube `@handle`), attributed to your key's project. Every profile endpoint used is `$0.001`.
