Turning Two Years of TikTok Bookmarks Into a Reading List

Turning Two Years of TikTok Bookmarks Into a Reading List

tl;dr - I had a TikTok collection full of book recommendations, collected over roughly two years, and no sane way to read it. So I pointed agents at the mess, made them OCR the videos and image slides, and ended up with 3,217 book mentions across 412 TikToks.

This started in the deeply respectable way most personal data projects start: I had been tapping the little bookmark button on TikTok for years and pretending that counted as organization.

To be fair, it sort of did. I had a collection for books. When BookTok threw some new grimdark fantasy list, sci-fi ranking, or suspiciously enthusiastic recommendation for Red Rising at me, I saved it. The problem is that TikTok book recommendations are not really data. They are videos, captions, subtitles, image carousels, cover shots, creator patter, stitched audio, and sometimes a single blurry slide with twelve titles on it.

So after a couple of years of this, I had something that looked like a reading list but behaved more like a junk drawer.

I wanted a boring table:

  • TikTok URL
  • books recommended in it
  • evidence for each recommendation
  • total count by book

Simple enough, except the books were not in one place. Some were in the description. Some were in the auto-generated subtitles. Some were in the video itself. A lot were in TikTok's photo-mode slides, which still have URLs that look like /video/{id} because why make this easy?

Anyway, I had agents now. This seemed like exactly the sort of fiddly task they should be good at.

Getting The Pile

The first step was getting the collection out of TikTok. I used the logged-in web API call behind the collection page and paged through it until I had the whole thing locally.

That gave me 412 TikToks.

At this point I had metadata: IDs, URLs, authors, descriptions, subtitle links where TikTok exposed them, and for photo-mode posts the imagePost.images array. That last bit ended up mattering a lot.

I did the obvious first pass:

  • parse descriptions for explicit "Books mentioned" lists
  • fetch subtitle files where available
  • pull structured metadata out of the API response
  • aggregate title counts conservatively

That got a decent chunk of the way there, but not nearly all the way. BookTok is not a well-formed CSV file, despite my personal wishes.

The First Wrong Pass

The next assumption was that the leftovers were video-only.

So I downloaded the remaining TikToks with yt-dlp, sampled every fifth frame with ffmpeg, OCR'd those frames locally with Apple's Vision framework, pulled audio to WAV, and ran local Whisper STT on it. Then I batched the OCR/STT text to subagents and had them extract book titles instead of trying to hand-roll a parser for "bookish human speaking over screenshots."

This was useful, but it also produced a weird result. A bunch of the "videos" had no video stream. They had an audio track and a cover image. The OCR looked like:

TOP 10 SCIENCE FICTION NOVELS OF THE 2000S

Which is not, strictly speaking, the list.

This is where Austin from twenty minutes later was smarter than Austin from twenty minutes earlier: those were not normal videos. They were TikTok photo-mode posts. TikTok shows them at /video/..., but the API has an imagePost object with every slide in the carousel.

Back to the scraper.

OCR, But Actually The Slides This Time

The corrected pass used imagePost.images directly. For each unresolved TikTok, I downloaded every slide image and OCR'd each slide independently. This was the missing step.

The final unresolved batch was:

  • 74 photo-mode slide decks
  • 683 individual slide images
  • 136,788 characters of fresh OCR
  • 0 download/OCR errors

Those slide decks added 609 more recommendation mentions by themselves.

The extraction workflow was pretty simple:

  1. Save the raw API pages locally.
  2. Fetch descriptions, subtitles, and image slides.
  3. Run local OCR and STT.
  4. Split the resulting text into small batches.
  5. Send each batch to a subagent with a strict JSON schema.
  6. Merge the results into one TikTok-to-recommendations map.
  7. Rebuild aggregate counts from that map.

The subagent part is worth calling out. I did not want to pretend that "OCR text from a TikTok slide" is easy to parse with regex. Sometimes the title is next to the author. Sometimes the author is half missing. Sometimes the slide has blurbs, rankings, UI text, and a book cover all smashed together. The useful unit of work was not "extract all capitalized words." It was "look at this messy evidence and decide which titles are clearly recommendations."

That is a good agent task. Bounded, checkable, annoying, and mostly judgment rather than architecture.

The Result

After the corrected slide pass, the catalog covered all 412 TikToks.

The final numbers:

  • 412 TikToks cataloged
  • 3,217 TikTok-level recommendation mentions
  • 1,634 unique normalized recommendations
  • 683 image slides OCR'd in the final correction pass
  • 0 items left in the review queue

The top recommendations were not shocking, but they were satisfying:

RankBook / SeriesCount
1Red Rising52
2Dungeon Crawler Carl31
3Dune25
4Project Hail Mary25
5The Sword of Kaigen25
6Sun Eater23
7The Poppy War22
8The First Law21
9The Fifth Season20
10Piranesi19
11Mistborn19
12A Song of Ice and Fire18
13Blood Over Bright Haven17
14The Wheel of Time16
15Assassin's Apprentice16
16Children of Time16

Red Rising being number one by a mile is maybe the least surprising thing that has ever happened on BookTok. I am not complaining. It just feels like the algorithm has a quota.

The Weirdly Useful Part

The useful part of this was not that I got a list of books. Though, yes, I did get a list of books, and my TBR is now less a list and more a zoning problem.

The useful part was that this was a genuinely personal dataset that I could not reasonably process by hand. It was too big to casually inspect, too messy for a simple script, and too small/weird to justify building some polished product around it.

That is where agents fit nicely.

Not in a "replace all software" way. More in a "take this pile of semi-structured personal exhaust and turn it into something I can actually use" way.

The workflow was not magic. It still needed me to notice when the first pass was wrong. It still needed local OCR. It still needed API spelunking. It still needed schema checks, merge scripts, and a final sanity pass. But the agents made the middle part tractable: hundreds of small judgment calls over messy captions, slides, subtitles, and OCR fragments.

That feels like the shape of a lot of useful agent work right now. Not a shiny demo. Not a chatbot pretending to be a database. Just a patient little assembly line for all the annoying glue work between "I have this somewhere" and "I can use this now."

At the end of the day, I still have too many books to read.

But now at least I know which ones TikTok has been yelling at me about for two years.

Show Comments