Tony Wang5 min readHow to Scrape TikTok Videos by Location in 2026
Search a place on TikTok, page every video tagged there, and pull English transcripts. Tested on one Chicago coffee shop: 68 videos from 65 creators.
To scrape every TikTok video tagged at a venue, search the place by name to get its poi_id_str, then page the place's videos with the returned cursor until has_more is false. For one Blue Bottle Coffee in Chicago that returned 68 videos from 65 creators, posted between December 2023 and October 2026. Add the video subtitles endpoint and you get English transcripts for the videos TikTok has captions for. This guide walks through the calls, shows what came back on 2026-10-26, and lists where the numbers stop being reliable.
Why search by place instead of by keyword
A keyword search matches what a creator typed. A place search matches where they tagged the video. Those are different sets.
At this Blue Bottle, 46 of the 68 videos (68%) have "blue bottle" in the caption or hashtags. The other 22 do not. Someone posts a matcha review, tags the location, and writes "worth the walk along the river". A caption search for the brand misses it. A place search does not.
Step 1: Find the place
search/place takes a keyword and returns TikTok's place records, each with a poi_id, coordinates, a parent area and a video count.
curl "https://api.crawlora.net/api/v1/tiktok/mobile/search/place?keyword=Blue%20Bottle%20Coffee&count=10" \
-H "x-api-key: $CRAWLORA_API_KEY"
The rows sit under data.poi_info.poi_info. Five of the ten we got back:
| Location (parent area) | poi_id_str | video_count in search |
|---|---|---|
| Chicago, Wolf Point (Cook) | 21568226263071439 | 94 |
| Washington, DC ("Blue Bottle Coffee Shop") | 22535865257999865 | 149 |
| Las Vegas (Clark) | 42203860783173656 | 58 |
| Washington, DC | 20442395111668790 | 17 |
| Oak Brook (DuPage) | 42203861103856574 | 13 |
The route returns the first page only, up to 30 rows. A count above 30 is rejected.
Step 2: Read the place record
place/info is the cheap lookup: about 6 KB instead of the megabyte-sized place detail page.
curl "https://api.crawlora.net/api/v1/tiktok/mobile/place/info?poi_id=21568226263071439" \
-H "x-api-key: $CRAWLORA_API_KEY"
For the Chicago location it returned a 4.4 rating from 21 reviews, 148 favorites, opening hours, coordinates and a share URL. It also returned video_count: 0, which is wrong, as the next step shows.
Step 3: Page every video
place/videos returns the app's full video objects, about 146 fields each. count is a hint, not a size: our four pages held 16, 16, 24 and 12 videos. Use the returned cursor for the next page and stop when has_more is false. There is no sort control, and each page was between 1 and 2 MB, so pace your calls.
import os, time, requests
BASE = "https://api.crawlora.net/api/v1/tiktok/mobile"
H = {"x-api-key": os.environ["CRAWLORA_API_KEY"]}
def get(path, **params):
r = requests.get(f"{BASE}/{path}", headers=H, params=params, timeout=60)
r.raise_for_status()
return r.json()["data"]
rows = get("search/place", keyword="Blue Bottle Coffee", count=10)["poi_info"]["poi_info"]
place = next(p for p in rows if p["parent_poi"] == "Cook")
poi_id = place["poi_id_str"]
videos, cursor = [], None
while True:
page = get("place/videos", poi_id=poi_id, count=17, **({"cursor": cursor} if cursor else {}))
videos += page["aweme_list"]
if not page["has_more"]:
break
cursor = page["cursor"]
time.sleep(3) # the upstream throttles bursts
print(len(videos), "videos,", len({v["author"]["unique_id"] for v in videos}), "creators")
# 68 videos, 65 creators
What 68 videos at one coffee shop look like
| Measure | Value |
|---|---|
| Videos retrieved | 68 |
| Distinct creators | 65 |
| Earliest and latest post | 2023-12-17 and 2026-10-21 |
| Posted in 2023 / 2024 / 2025 / 2026 | 1 / 15 / 19 / 33 |
| Total plays | 272,615 |
| Median plays per video | 849 |
| Most-played video | 102,127 (37% of all plays) |
| Share of plays in the top three videos | 59% |
| Caption language | 63 English, 2 Spanish, 3 undetermined |
| Name the brand in caption or hashtags | 46 of 68 |
The shape is the usual one for a single venue: one video above 100,000 plays, a few in the tens of thousands, and a long tail of posts nobody much watched. If you rank places by total views, one viral post can decide the order.
Step 4: Add transcripts
video/subtitles returns a video's captions translated into a language you choose, as raw WebVTT and as parsed cues with start and end times. It supports 16 target languages. A Spanish-language video from this place came back as 12 English cues.
def transcript(video_id, language="en"):
r = requests.get(f"{BASE}/video/subtitles", headers=H,
params={"video_id": video_id, "language": language}, timeout=60)
if r.status_code == 400: # "has no captions available"
return None
r.raise_for_status()
return " ".join(c["text"] for c in r.json()["data"]["cues"])
We ran it on the 22 videos whose captions do not name the brand:
- 5 returned English subtitles.
- 16 returned HTTP 400, "has no captions available in en".
- 1 request timed out.
- 2 of the 5 transcripts say "Blue Bottle" aloud. One reviews an iced matcha by name.
So transcripts recover some mentions that neither the caption nor the hashtags carry, but not most. Treat a 400 as "no captions", not as an error to retry.
What the web endpoint already gives you
The web tiktok/post/{id} response for a video already carries its place: name, address, city and the place id. If you have a video and want its location, you do not need the mobile routes. What the web side lacks is a way to start from a venue.
| Need | Web endpoints | Mobile endpoints |
|---|---|---|
| Location of a video you already have | post/{id} returns the place name, address and id | not needed |
| Find a venue, then list its videos | no place route | search/place, then place/videos |
| Captions | original-language track in the post detail | translated into 16 languages, parsed into cues |
Limits we hit
video_countis unreliable. The Chicago place showed 94 in search and 94 on oneplace/infocall, then 0 on the next four. Paging returned 68. The Oak Brook location showed 0 videos in one search and 13 in another. Page untilhas_moreis false and count what you receive.- ID rounding. Covered above: use
poi_id_str. - Search is first-page only. You get at most 30 places per query, so narrow the keyword with a city name.
- Variable page size and weight. Pages held 12 to 24 videos and weighed 1 to 2 MB.
- No sort. You cannot ask for the most-played first. Page everything, then sort.
- Missing captions. 16 of 22 videos had none in English.
- Throttling. One request in our run timed out. A three-second pause between pages worked.
- A snapshot. All figures are from 2026-10-26. A place keeps gaining videos.
Legal and privacy notes
Everything here is public, but the 65 creators are individuals. Keep the video id, handle and text you need, not whole profiles, and read TikTok's terms before running this at volume. See is web scraping legal. This is not legal advice.
Where this gets used
- Chain and franchise comparison. Pull each location of a brand and compare video volume and rating by site.
- Venue and tourism monitoring. Track what visitors post at a place you manage or promote.
- Finding local creators. The 65 handles here are people who already visited. Check consent before contacting anyone.
Start collecting
Reference pages for the calls in this guide: place search, place videos and video subtitles. Try a call in the Playground and check pricing. The rest of the TikTok routes are on the TikTok API page. For profiles, hashtags and comments, read how to scrape TikTok, and for a comparison of vendors see best TikTok scraper APIs in 2026.
Frequently asked questions
How do I scrape TikTok videos by location?
Search the place by name with search/place, keep the poi_id_str from the result, then call place/videos with that id and follow the returned cursor until has_more is false. For one Blue Bottle Coffee in Chicago this returned 68 videos from 65 creators, posted between December 2023 and October 2026.
Why search by place instead of by keyword?
A keyword search matches what the creator typed; a place search matches where they tagged the video. At the Chicago Blue Bottle, 22 of 68 videos (32%) never mention the brand in the caption or hashtags, so a caption search for the name would not find them.
Is the place video_count reliable?
No. The same Chicago place showed 94 in search and on one place-info call, then 0 on the next four calls, and paging place/videos returned 68. Page until has_more is false and count what you receive instead of trusting video_count.
Why does my TikTok place ID not work?
Use poi_id_str, not poi_id. The numeric poi_id is a JSON number above 2^53, so most parsers round it and you end up requesting a different place.
Can I get TikTok video transcripts?
Where TikTok has captions, yes: the video subtitles endpoint returns them translated into one of 16 target languages, as WebVTT and as parsed cues with timestamps. Coverage is partial. Of 22 videos we tested, 5 had English captions and 16 returned HTTP 400 for no captions.
Does the web post endpoint return a video's location?
Yes. The web tiktok/post/{id} response carries the place name, address and id for a video you already have. What it lacks is a way to start from a venue and list its videos, which the mobile place routes provide.