# Changelog of TikTok Scraper: Videos, Hashtags, Profiles & Comments (`humble-echidna/tiktok-scraper`) Actor

- **URL**: https://apify.com/humble-echidna/tiktok-scraper/changelog.md
- **Full Actor documentation**: https://apify.com/humble-echidna/tiktok-scraper.md

## Changelog

Versions follow MAJOR.MINOR.PATCH (`src/version.py`); Apify shows MAJOR.MINOR from `.actor/actor.json`.
Every run logs its version and records it in the `RUN_STATS` key-value record.

### 0.1.2 (2026-10-20)

- A profile's list of latest videos (its embed page) is retried when TikTok answers "too many requests" (HTTP 429),
  as every other page already was. Before, one 429 there ended the profile with no videos.
- No change to output fields or price.

### 0.1.1 (2026-10-16)

- A run that returns nothing (every input bad, private, blocked or unreachable, or an empty input) now ends
  SUCCEEDED with an empty dataset and the reason as its status message and in the log, instead of FAILED. Only an
  unexpected error still fails the run. `RUN_STATS` keeps the reason as before.
- No change to output fields or price.

### 0.1.0 (2026-10-14)

First release.

- Videos from hashtags (TikTok's own hashtag page, read in a headless browser because its list needs the page's
  request signing), sounds (the same way), profiles (the ~10 latest from the profile's embed card, each video page
  read in full) and video or photo links (short links resolved), as one flat row per video.
- Comments per video and replies per comment as rows of their own, tied to the video by `videoId`.
- Optional profile rows with exact follower, following, like and video counts.
- Free filters: only videos newer than a date or age (profile videos skipped by the upload time in their id, before
  fetching), and only new since the last run (per hashtag, sound, profile and video, remembered 120 days).
- Charged per row through two events: `video` (videos and profile rows) and `comment` (comments and replies); the
  dataset item event is unpriced, so a row is charged once. "Max results per run" and the maximum cost per run are
  honoured across both, before the work.
- Failure isolation: a failing source, video page or comment thread only affects itself; every source's outcome
  (returned, skipped by filters, why a list ended, TikTok's reason for a failure) is in `RUN_STATS`.

Sources and terms (ACTOR-CHECKLIST 0 and 6): TikTok publishes no API for this; the actor reads tiktok.com's own
public pages and the requests they make (`/@user`, `/embed/@user`, `/@user/video/<id>`, `/tag/<name>`,
`/music/<name>-<id>`, `/api/comment/list/`, `/api/comment/list/reply/`, and in the browser `/api/challenge/item_list/`
and `/api/music/item_list/`). robots.txt (read 2026-10-14) allows `/tag` and `/music` for every crawler and disallows
`/embed/@`, `/search?` and some APIs; TikTok's Terms of Service (https://www.tiktok.com/legal/page/us/terms-of-service/en,
read 2026-10-14) apply to visitors without an account (§3.2) and forbid extracting data by automated means without
written approval (§3.4). Read anyway under Michael's platform exception (PLAN.md "Exclusions lifted", 2026-10-14):
logged out only, no accounts or cookies of anyone's, polite pace, takedown on request; the README says so.
