While TikTok started as an app for dancing and music, anyone who's used the app knows that it's grown into something much bigger. I've learned so many things from random accounts: history lessons, travel advice, "life hacks that have become unconscious standard practices", you name it!
Cooking is a big topic for me. I come across lots of delicious looking recipes and "like" them to revisit later. But TikTok's interface for searching through liked videos is half-baked and lacks basic features for searching through a large list of videos.
So even though I want to try all of these recipes, I get stuck trying to find them (and then end up liking more videos to continue to bury them in my pile of likes).
But I figured, TikTok has a public API, how hard would it be to build a project to solve this?
The answer: not that hard 😄 though with some hacks. Here's what I ended up building: tiktok-recipes.deno.dev. Will walk through how I did it below!
TikTok provides a public
oembed API that will retrieve metadata for a video. It's as simple as a
url is the full path to the video on TikTok.
With a simple script around this, a list of videos can be iterated upon to fetch and save metadata to a static file. All that's needed is the list of recipes...
This step was boring 🥱 there's no getting around needing to sift through all of the videos I've liked to save the URLs for the ones that are recipes. Ended up scrolling for a while and opening a bunch of tabs then doing a trick to bookmark/export those tabs.
I used fresh as it's been my framework of choice lately. It includes preact, typescript & twind by default. The interface is a simple two-pane component that renders a scrollable list of video titles on the left and a
<video> element on the right. But while it'd be possible to just embed the TikTok entirely in an iFrame, I'd much rather only load the content I want.
Ideally I could just link the
src of the video from metadata, but that would be too easy. The source URL isn't included in this blob so unfortunately it requires a hackier approach to obtain. But I came up with a solution for this that requires minimal code (<20 lines total)!
I covered this in an earlier post, you can read more about it here:
tl;dr: scrape the page for the media URL inside the server-generated client-side blob. Unfortunately there doesn't appear to be a simpler way to do this at the moment (let me know otherwise).
This is easily to implement with a fresh handler though! And since this happens on the server it gets around CSP restrictions that prevent loading content from another website. Here's the full source for the handler.
Now that all the pieces are in place, all that's left is to connect the request flow and ensure client state works correctly! With some simple logic to handle basic actions and loading states (showing video thumbnail initially & adding a play indicator to load video), it's looking pretty usable. Definitely nothing to write home about but gets the job done.
The list ordering is randomized on each pageload for a different experience each time I visit. And, importantly, I added a simple text search as well to filter results - a basic feature TikTok's liked videos page still doesn't support.
If you didn't catch the link earlier here it is in action: tiktok-recipes.deno.dev. Feel free to poke through the recipes I find interesting or read through the source (below) to see the full project (or fork it & create your own page for any category of TikToks you'd like easier access to). Thanks for reading!
Indexing recipes I've liked on TikTok for easier access.
deno task start
This will watch the project directory and restart as necessary.
deno task fetch:tiktoks
This will fetch metadata for videos in