# GET /v1/tiktok/video: TikTok no-watermark API

One TikTok video or photo post by its link (short vm.tiktok.com links too): the video without the watermark, the soundtrack, a photo post's pictures, caption, hashtags, author, time, and views, likes, comments and shares. A number is null when it is not exact. File links are temporary: download right away.

- Call: `GET https://storiesfly.com/api/v1/tiktok/video`
- Price **1 request**
- Answers up to **15 minutes** old

## Parameters

All parameters go in the query string.

| Name | Type | Sent | Description |
| --- | --- | --- | --- |
| `url` | string | required | Link to one TikTok video or photo post: tiktok.com/@user/video/<id>, /photo/<id>, or a vm.tiktok.com, vt.tiktok.com or tiktok.com/t/ short link. |

## Example request

Put your own key in the header, or in the apiKey option of the npm client.

### cURL

```bash
curl "https://storiesfly.com/api/v1/tiktok/video?url=https%3A%2F%2Fwww.tiktok.com%2F%40khaby.lame%2Fvideo%2F7697307919943060767" \
  -H "X-Api-Key: sf_live_your_key"
```

### JavaScript

```javascript
const res = await fetch(
  "https://storiesfly.com/api/v1/tiktok/video?url=https%3A%2F%2Fwww.tiktok.com%2F%40khaby.lame%2Fvideo%2F7697307919943060767",
  { headers: { "X-Api-Key": process.env.STORIESFLY_KEY } }
);
const data = await res.json();
```

### Python

```python
import os
import requests

r = requests.get(
    "https://storiesfly.com/api/v1/tiktok/video",
    params={"url": "https://www.tiktok.com/@khaby.lame/video/7697307919943060767"},
    headers={"X-Api-Key": os.environ["STORIESFLY_KEY"]},
)
data = r.json()
```

## Example response

200 OK · X-Units-Charged: 1

```json
{
  "id": "7697307919943060767",
  "url": "https://www.tiktok.com/@khaby.lame/video/7697307919943060767",
  "author": {
    "username": "khaby.lame"
  },
  "taken_at": 1792169181,
  "taken_at_iso": "2026-10-16T16:46:21.000Z",
  "caption": "I guess is time to retire #learnfromkhaby #comedy 🥊",
  "hashtags": [
    "learnfromkhaby",
    "comedy"
  ],
  "media_type": "video",
  "thumbnail_url": "https://p16-common-sign.tiktokcdn-us.com/tos-useast8-p-0068-tx2/oQbHQmFfa5VY3NlkEGDAQT00RzqAqBOETlEafj~tplv-tiktokx-cropcenter-q:300:400:q70.jpeg",
  "video_url": "https://v16-notes.tiktokcdn-us.com/2be808f08705c24ce524dc1c6be75bfd/6ad86eac/video/tos/useast8/tos-useast8-ve-0068c001-tx2/oUNaVlmzDIfimS0TAHFgVVRYNBfQqDEQExA5…",
  "video_url_sd": "https://v16m.tiktokcdn-us.com/9a847fe287ca9832a70c225bb36490c7/6ad86eac/video/tos/useast8/tos-useast8-pve-0068-tx2/okAtBQJDE2EBABOobPVaUIr8ztS8Vii6QRmMZ/",
  "audio_url": "https://v16-ies-music.tiktokcdn-us.com/9faf1ca1cfd2c177d0d52a67236dfd58/6ae154d5/video/tos/useast8/tos-useast8-v-27dcd7-tx2/o0lYCTaBi4zgW3APV1PCJGRIGuUvvti6VAM…",
  "images": [],
  "video_duration": 9,
  "views": 3305439,
  "likes": 273186,
  "comments": 6525,
  "shares": 31470
}
```

A real answer, shortened: lists are cut to two items and long texts to 160 characters.

## Price and freshness

A call takes 1 request. Free requests are spent first, then your balance. The [pricing](https://storiesfly.com/developers/pricing) page has the rates.

Answers are kept for up to 15 minutes. Asking again inside that time returns the same answer and takes 1 request again.

## Errors

A failed call answers with an HTTP status and a body `{error, code}`. These are the codes this endpoint gives. [Errors and what is charged](https://storiesfly.com/developers/docs#errors) covers all of them.

| Status | Code | When |
| --- | --- | --- |
| `400` | `bad_request` | A parameter is missing or wrong. `fields` lists the names. Free. |
| `401` | `unauthorized` | The `X-Api-Key` header is missing or the key is wrong. Free. |
| `402` | `credits_exhausted` | The free requests and the balance are used up. Top up in the [dashboard](https://storiesfly.com/developers/dashboard). Free. |
| `403` | `telegram_required` | The account behind the key is not linked to Telegram. The answer has a `link_url` to do it. Free. |
| `404` | `not_found` | The video does not exist, is private or was removed. Charged like an answer. |
| `429` | `rate_limited` | More requests in a second than your level allows, more than this group can take at once, or more than 1,000 TikTok and download calls today. Wait for the `Retry-After` header. Free. |
| `500` | `internal_error` | A fault on our side. Retry shortly. Refunded. |
| `503` | `upstream_unavailable` | Our side failed or timed out. Retry shortly. Refunded. |

## Questions about this endpoint

### Which links can I send?

A video or photo link of the form tiktok.com/@user/video/<id> or /photo/<id>, and the short share links vm.tiktok.com, vt.tiktok.com and tiktok.com/t/. A profile link is refused with `bad_request`.

### Is the video without the watermark?

Yes. `video_url` is the file without the watermark, in the best quality offered, and `video_url_sd` a smaller one when there is one. Links stop working within hours, so download the file soon after the call.

### Why is a number null?

`views`, `likes`, `comments` and `shares` are given only when they are exact; otherwise they are `null`, never a guess. For the files alone, without the numbers, there is [download](https://storiesfly.com/developers/docs/download).

## Related endpoints

- [GET /v1/download](https://storiesfly.com/developers/docs/download): Files of an Instagram post or reel, or a TikTok video, by link
- [GET /v1/tiktok/user/videos](https://storiesfly.com/developers/docs/tiktok-user-videos): A TikTok account's latest videos with their numbers
- [GET /v1/tiktok/user/profile](https://storiesfly.com/developers/docs/tiktok-user-profile): TikTok profile with followers, following, likes and video count

## Links

- [This page on the site](https://storiesfly.com/developers/docs/tiktok-video)
- [Instagram data API](https://storiesfly.com/developers): what the API is and what it returns
- [Pricing](https://storiesfly.com/developers/pricing): rates, examples and billing rules
- [Documentation](https://storiesfly.com/developers/docs): quick start, authentication, errors and every endpoint
- [OpenAPI file](https://storiesfly.com/openapi.json): the whole API in one file
- [API dashboard](https://storiesfly.com/developers/dashboard): get a key and top up
- [Changelog](https://storiesfly.com/developers/changelog): what changed and when
