TikTok location data sits behind two calls. One turns a place ID into the record of the location itself - its name, address, city, category tags and the number of videos tagged there. The other returns the videos filmed at that spot. This guide covers both: the place-info endpoint for the point of interest record, the place-posts endpoint for the feed, where the place ID has to come from in the first place, which fields the live response actually contains, and the privacy line you should not cross with this data.
What a TikTok place ID actually is
Internally TikTok calls a location a POI - point of interest. A POI can be a restaurant, a shopping mall, a beach, a city district or a country. Each has a numeric identifier stored as a string, and that identifier is the only thing either endpoint needs. The example used throughout this post is 22535796481538024, which resolves to District 12 in Ho Chi Minh City - a district-level POI rather than a venue, which is useful for showing how the category fields behave.
One thing to be clear about up front: there is no free-text place search. You cannot ask the API for "coffee shops in Lisbon" and get a list of POIs back. Place IDs are something you collect, store and reuse, which makes the next section the important one.
Where the placeId comes from
Every video item that was tagged with a location carries a poi object, and that object contains the ID. This is the reliable harvesting route. On the item schema the block looks like this:
"poi": {
"id": "22535796481538024",
"name": "District 12",
"address": "Ho Chi Minh City, Vietnam",
"city": "Ho Chi Minh City",
"cityCode": "1580578",
"country": "",
"countryCode": "1562822",
"province": "",
"category": "District",
"fatherPoiId": "",
"fatherPoiName": "",
"ttTypeCode": "19a3a2",
"ttTypeNameTiny": "District",
"ttTypeNameMedium": "Places",
"ttTypeNameSuper": "Place and Address",
"type": 0,
"typeCode": ""
}
You will find that block on items returned by place-posts itself and on items from a repost feed - the field table in the guide to getting TikTok reposts via API lists it. Any feed you are already paging is worth scanning for it, because the cost is zero: you have paid for the page anyway. The numeric ID also appears at the end of a TikTok place page URL, which is handy when you have one specific venue in mind.
So run a harvester over the feeds you already collect and build your own POI table as a side effect:
def harvest_places(items):
"""Pull unique POI records out of any itemList."""
found = {}
for it in items:
poi = it.get("poi")
if not poi or not poi.get("id"):
continue
found[poi["id"]] = {
"name": poi.get("name"),
"address": poi.get("address"),
"city": poi.get("city"),
"category": poi.get("category"),
}
return found
Once a place ID is in your table it never needs resolving again. Store it next to the venue name and reuse it for every future call.
Step 1: resolve the ID with place-info
The base URL is https://api.primeapi.co/ and authentication is a single header, X-PrimeAPI-Key. place-info takes one required parameter, placeId, and nothing else. The full request reference is in the PrimeApi documentation, and you can fire a call without writing code first in the API playground.
curl
curl -s "https://api.primeapi.co/place-info?placeId=22535796481538024" \
-H "X-PrimeAPI-Key: YOUR_API_KEY"
Node.js (Axios)
const axios = require("axios");
const KEY = "YOUR_API_KEY";
async function getPlace(placeId) {
const res = await axios.get("https://api.primeapi.co/place-info", {
params: { placeId },
headers: { "X-PrimeAPI-Key": KEY }
});
console.log("Remaining credits:", res.headers["x-primeapi-balance"]);
return res.data.poiInfo;
}
getPlace("22535796481538024")
.then(info => {
const p = info.poi;
console.log(p.name, "|", p.address);
console.log("category:", p.category, "/", p.ttTypeNameTiny);
console.log("videos tagged here:", info.stats.videoCount);
})
.catch(e => console.error(e.response ? e.response.data : e.message));
Reading the POI record
The response nests everything under poiInfo. Inside it, poi holds the location record and stats holds a single counter. Alongside poiInfo you also get shareMeta (with title and desc, which mirror the name and address), an extra object carrying logid and now, log_pb, and the status trio statusCode, status_code and status_msg.
| Field | What it holds |
|---|---|
poi.id | The place ID, echoed back as a string. Use it as your primary key. |
poi.name | Display name of the location, for example District 12. |
poi.address | A single formatted address string. In the sample this was Ho Chi Minh City, Vietnam - broad for a district, more precise for a venue. |
poi.city, poi.province, poi.country | Administrative parts. All three can be empty strings; only city was populated in the sample. |
poi.cityCode, poi.countryCode | TikTok's internal numeric geo codes, as strings. These are not ISO codes - the sample returned 1562822 for Vietnam. Treat them as opaque join keys inside TikTok data only. |
poi.category | The plain category label, District in the sample. For venues this is where you see the business type. |
poi.ttTypeNameTiny / ttTypeNameMedium / ttTypeNameSuper | TikTok's three-level taxonomy, narrow to broad. The sample gave District, Places, Place and Address. Group by the Medium or Super level when you are bucketing many POIs. |
poi.ttTypeCode, poi.typeCode, poi.type | Machine-readable codes for the same taxonomy. ttTypeCode was 19a3a2; typeCode was empty and type is an integer. |
poi.fatherPoiId, poi.fatherPoiName | The parent POI, when one exists - a venue inside a mall, for instance. Both were empty for a district. When fatherPoiId is populated you can feed it straight back into place-info and climb the hierarchy. |
poi.poiDetailTags | An array of detail tags on the location. |
poi.isClaimed, poi.isCollected, poi.indexEnabled | Booleans. isClaimed indicates a business has taken ownership of the listing, which is a useful filter when you are separating managed venues from crowd-created pins. |
poi.phoneInfo, poi.pictureAlbum, poi.allLevelGeoPoiInfo | Nested objects. phoneInfo exposes an exist flag, pictureAlbum a totalCount. |
stats.videoCount | How many videos are tagged at this location. The single most useful number in the response. |
There are no coordinates
Worth stating plainly, because it is the field people most often expect: the live response contains no latitude or longitude. There is no lat, no lng, no geometry object anywhere in the payload. What you get is text - a name, an address string and administrative labels. If you need a pin on a map, concatenate poi.name with poi.address, run that through a geocoding service and cache the result against the place ID so you pay for the geocode once. Do not try to derive a location from cityCode or countryCode; they are internal identifiers with no public mapping.
Step 2: pull what people film there with place-posts
place-posts takes the same placeId plus optional count for page size and cursor for paging, starting at 0. It returns a standard feed envelope: itemList, a cursor string, a boolean hasMore, plus the same extra, log_pb and status fields. The cursor is opaque - a live sample came back as the string "644602", which is neither an index nor a timestamp - so never compute it yourself. Pass the value back verbatim and stop when hasMore turns false.
import requests
BASE = "https://api.primeapi.co"
HEADERS = {"X-PrimeAPI-Key": "YOUR_API_KEY"}
def place_posts(place_id, count=20, max_pages=10):
cursor = "0"
for _ in range(max_pages):
r = requests.get(f"{BASE}/place-posts",
params={"placeId": place_id, "count": count, "cursor": cursor},
headers=HEADERS, timeout=15)
r.raise_for_status()
data = r.json()
for item in data.get("itemList", []):
yield item
if not data.get("hasMore"):
break
cursor = data.get("cursor")
if __name__ == "__main__":
for item in place_posts("22535796481538024"):
print(item["id"], "@" + item["author"]["uniqueId"], item["desc"][:60])
Each entry in itemList is a full video record: id, desc, createTime, an author block with uniqueId, secUid, nickname, verified and the avatar sizes, authorStats and authorStatsV2 with that creator's follower and video totals, a music block, a challenges array of hashtags, item flags such as isAd and isReviewing, and the poi object echoed back on the item. That last one matters more than it looks: it confirms which location each video was actually tagged at, which is how you verify a feed rather than assuming it.
The items here do not carry an engagement block you can rely on. When you need real play, like, comment and share numbers, take the item id and call post-detail, which returns stats and statsV2 under itemInfo.itemStruct - the full field tour is in the post on getting TikTok video data via API. Enriching costs 1 extra credit per video, so filter first and enrich second.
What the two calls give you together
Run in sequence, they answer a question no single feed can. stats.videoCount tells you how much attention a location is attracting in absolute terms; the authors in place-posts tell you who is producing that attention and how large their audiences are. Poll place-info daily and diff videoCount and you have a growth curve for a venue at one credit per day. That is the backbone of local business research with TikTok place data. To profile the creators who show up repeatedly, resolve their handles with userinfo-by-username, covered in getting TikTok user data via API.
Privacy and ethics of location data
Location data deserves more care than a follower count, so be deliberate about how you use it.
What these endpoints return is public by construction. A POI record is a place listing, not personal information, and the videos in place-posts are public posts whose creators chose to attach a location tag. Counting how many videos were filmed at a shopping centre is ordinary market research on aggregate data.
The line is the individual. Taking one creator, collecting the poi block from every video they have posted and assembling a map of where they have been is a different activity entirely - that is building a movement profile from scattered public fragments, and it is the kind of processing that privacy regimes such as the GDPR treat seriously regardless of the data being public. The same applies to anything that could identify a home address or a routine. Keep your analysis at the place level, aggregate before you store, and do not build per-person location histories.
Two rules follow. Delete raw item records once you have the aggregates you needed, and if a video disappears from TikTok, drop it on the next run - a creator removing a post is a signal to honour. PrimeApi is an independent service, not affiliated with or endorsed by TikTok or ByteDance, so compliance with TikTok's terms of service and with the privacy law where you operate is yours to manage.
Credits, paging and limits
Both endpoints cost exactly 1 credit per request, whether the answer is a full page or an empty itemList, and the remaining balance comes back in the X-PrimeAPI-Balance header - log it and alert on it. The default rate limit is 100 requests per minute, which is comfortable for a paging loop but worth staggering if you sweep many POIs at once. Responses are real time with no caching and typically land in about a second. New accounts get 50 free credits at sign-up, and volume tiers start at $9.90 for 2,500 credits on the pricing page.
Known limits, stated plainly: no coordinates, no place search by name, and no historical series - videoCount is a snapshot, so any trend has to be built by polling and diffing on your side. Empty or sparse fields are normal, especially country, province, typeCode and the parent POI pair, so never assume a string is populated.
Putting it together
The complete flow is short. Harvest place IDs from the poi block on video items you are already pulling and keep them in your own table. Call place-info once per ID to get the name, address, category tags and videoCount, and geocode the address externally if you need a map pin. Call place-posts with the same ID to see what is being filmed there, paging on the opaque cursor until hasMore is false. Enrich only the videos you actually care about with post-detail. Re-poll place-info on a schedule to turn a static record into a trend line. Two credits gets you a full picture of a location, and a daily credit keeps it current.
Frequently asked questions
What is a TikTok place ID?
It is the numeric string TikTok assigns to a point of interest - a venue, a district, a city, a landmark. In the API it appears as poi.id on video items and as the placeId query parameter on the place endpoints. The sample used throughout this guide is 22535796481538024, which resolves to District 12 in Ho Chi Minh City.
Where do I get a placeId from?
The dependable source is the poi block that TikTok attaches to any video item that was location-tagged. Pull a feed you already have access to, read item.poi.id, and you have a valid place ID with its name and address alongside it. The numeric id also appears at the end of a TikTok place page URL. There is no free-text place search endpoint, so plan to harvest IDs from feeds rather than look them up by name.
Does place-info return latitude and longitude?
No. The live response carries no coordinate fields at all. You get address, city, province, country and TikTok's internal cityCode and countryCode values, which are not ISO codes. If you need a point on a map, geocode the name plus address string with a separate geocoding service and store the result yourself.
What is the difference between place-info and place-posts?
place-info describes the location: its name, address, category tags and how many videos are tagged there. place-posts returns the videos themselves as a paged itemList. One tells you what a place is, the other tells you what people are filming there. Both take the same placeId and both cost 1 credit per call.
How much does a location lookup cost?
One credit per request, whatever comes back. A place lookup plus three pages of posts is 4 credits. New accounts start with 50 free credits, and the remaining balance is returned in the X-PrimeAPI-Balance response header on every call.
Is it acceptable to collect TikTok location data?
The place endpoints only return data that is already public: a venue record and videos whose creators chose to tag that venue. Aggregate work on venues and districts is normal market research. Building a movement history for a named individual is not - it turns public posts into surveillance and is likely restricted where you operate. Keep the analysis at the place level, respect TikTok's terms, and delete what you no longer need.