Every TikTok API scope in 2026, the exact fields each one returns, and why users can grant only part of what you asked for.
- TikTok API scopes can be granted partially: a user may approve user.info.basic and decline user.info.stats, so read the scope field in the token response.
- 4 scopes cover most builds: user.info.basic for identity, user.info.profile for username and bio, user.info.stats for counts, video.list for videos.
- Publishing needs 2 different scopes: video.upload drops a draft in the creator's inbox, video.publish posts directly.
- Approval and authorisation are separate gates: TikTok approves your app to ask, then each user still grants each scope.
- Access tokens last 24 hours and refresh tokens 365 days, and neither refreshes itself.
TikTok scopes are more granular than most platforms and they behave differently in 1 way that catches people out: a user can approve some of the scopes you requested and decline the rest.
TikTok's own documentation states it plainly. Users have the right to agree to only a subset of the scopes you requested. Your app then receives a token that works for part of what you built and fails for the rest, with no error at authorisation time.
What follows is every scope family, the exact fields each scope returns, the 2 gates between you and a user's data, and how to handle a partial grant. Everything here is from TikTok's developer documentation as of July 2026.
How do TikTok scopes differ from Meta scopes?
3 differences matter in practice, and the first one changes how you write your code.
- Partial grants are allowed. A user can approve
user.info.basicand declineuser.info.stats. Your integration has to cope with holding a valid token that cannot reach half the fields your UI renders. - Scopes are bundled into products. You do not request scopes freely. You add a product in the developer portal, such as Login Kit or Content Posting API, and that product carries its scopes. Content Posting API requires Login Kit, so the order matters.
- Field-level protection is explicit. TikTok protects sensitive fields with additional scopes rather than returning nulls. Request the field without the scope and the call fails rather than returning an empty value.
If you are comparing the 2 platforms directly, we mapped Meta's equivalent list in Instagram API permission scopes.
What does each Login Kit scope return?
These are the read scopes, and this table is the scope-to-field mapping most guides skip. Fields are requested through the fields query parameter on /v2/user/info/, and each one is gated by a specific scope.
| Scope | What it covers | Fields it returns |
|---|---|---|
user.info.basic | Identity and avatar | open_id, union_id, avatar_url, avatar_url_100, avatar_large_url, display_name |
user.info.profile | Public profile detail | username, bio_description, profile_web_link, profile_deep_link, is_verified |
user.info.stats | Account statistics | follower_count, following_count, likes_count, video_count |
video.list | The creator's video list | The list of videos posted by the authorising user, with their metadata |
2 notes on this table. user.info.basic is added by default to every app that has Login Kit, so you do not request it separately, and it is the only scope TikTok Minis supports alongside user.info.open_id.
The open_id and union_id distinction matters if you operate several apps. open_id is unique to a user within 1 application, so the same person has a different open_id in each of your apps. union_id is persistent for that user across every app under the same developer account. If you need to recognise a returning creator across products, union_id is the field to key on.
What does each Content Posting scope do?
2 scopes, and choosing the wrong one produces a product that behaves nothing like the one you specified.
| Scope | What it does | When to use it |
|---|---|---|
video.upload | Uploads content to the creator's TikTok inbox as a draft. The creator reviews and posts it themselves | Review workflows, agency approval flows, and any product where the creator wants the final say |
video.publish | Posts content directly, either immediately or scheduled | Scheduling tools and programmatic publishing where the creator has already approved the content in your product |
Content Posting API requires Login Kit as a prerequisite, so add Login Kit to your app first. And note that until your app passes its production audit, content published through the API is forced to private visibility regardless of the privacy setting the user chose at the consent screen. That trips people up during testing, because the flow completes successfully and the post is invisible.
The publishing flow itself is 3 calls rather than 1, and the rate limits are strict. We covered both in the TikTok API integration guide and the TikTok API rate limits guide.
If you want the fields without running an app audit for every platform, our per-platform coverage list is public. See the coverage list
What are the Research API scopes?
3 scopes, gated behind institutional eligibility rather than a standard app review. Commercial product building is not permitted under Research API terms.
| Scope | What it grants |
|---|---|
research.data.basic | Access to TikTok public data for research purposes |
research.adlib.basic | Access to public commercial data, meaning the ad library, for research purposes |
research.data.u18eu | Access to data from European users under 18, alongside other public data, for research purposes |
If you are a commercial platform and someone suggests the Research API as a shortcut to public data, it is not one. Using research credentials for a commercial use case risks losing access entirely.
What are the Data Portability scopes?
8 scopes, split across 4 data categories and 2 request types. This is the route a user takes to export their own data to your product, and it exists because of data portability obligations rather than as a general access mechanism.
| Data category | Single request | Ongoing requests |
|---|---|---|
| Everything available | portability.all.single | portability.all.ongoing |
| Posts and profile | portability.postsandprofile.single | portability.postsandprofile.ongoing |
| Activity data | portability.activity.single | portability.activity.ongoing |
| Direct messages | portability.directmessages.single | portability.directmessages.ongoing |
The single and ongoing split is the important part. A .single scope authorises 1 export. An .ongoing scope authorises repeated exports on the user's behalf. Request .single when you need a one-time import and .ongoing only when your product genuinely needs to keep pulling, because the broader permission is a harder ask at the consent screen.
What other scope families exist?
2 more, both narrow, and worth knowing so you do not go looking for them in the wrong product.
- Local Service:
local.product.manageto create and manage product listings,local.shop.manageto create and manage local shops, andlocal.voucher.manageto validate and redeem vouchers. - TikTok Minis: supports only
user.info.basicanduser.info.open_id. If you are building a Mini, the rest of this reference does not apply to you.
Why does approval not give you access?
Because there are 2 independent gates, and clearing 1 tells you nothing about the other.
- App-level approval. You add the product in the developer portal and request the scopes. TikTok approves your app to ask for them. This is the gate people think of as "getting access".
- User-level authorisation. Each individual user has to grant each scope at the consent screen. TikTok's documentation is explicit that being approved for a scope alone does not give you access to a user's data.
While your app is in sandbox, only accounts you have added as target users can connect at all. A sandbox integration can therefore work perfectly for your team and fail for every real user, which is the same shape of surprise Meta produces with Standard Access.
How do you handle a partial scope grant?
By reading the scope field that comes back with the token, and degrading the UI rather than throwing errors. The token response tells you exactly what you were granted.
// Token response. Note the scope field.
{
"data": {
"access_token": "act.example12345Example12345Example",
"expires_in": 86400, // 24 hours
"refresh_token": "rft.example12345Example12345Example",
"refresh_expires_in": 31536000, // 365 days
"open_id": "abcdefgh-1a2b-123c4-ab12-abc123abc1234",
"scope": "user.info.basic" // NOT what you requested
}
}
That last line is the whole point. You may have requested 4 scopes and been granted 1. Store what you were granted, not what you asked for, and check it before every call.
REQUESTED = ["user.info.basic", "user.info.profile",
"user.info.stats", "video.list"]
# Fields, keyed by the scope that unlocks them
FIELD_SCOPE = {
"open_id": "user.info.basic",
"display_name": "user.info.basic",
"avatar_url": "user.info.basic",
"username": "user.info.profile",
"bio_description": "user.info.profile",
"is_verified": "user.info.profile",
"follower_count": "user.info.stats",
"likes_count": "user.info.stats",
"video_count": "user.info.stats",
}
def fields_for(granted_scope_string):
granted = set(granted_scope_string.split(","))
return [f for f, s in FIELD_SCOPE.items() if s in granted]
# On connect, store the GRANTED scopes against the account
granted = token_response["data"]["scope"]
account.granted_scopes = granted
# Then request only the fields you are entitled to
fields = fields_for(granted)
GET f"/v2/user/info/?fields={','.join(fields)}"
# And tell the user what is missing, rather than showing a zero.
missing = set(REQUESTED) - set(granted.split(","))
if "user.info.stats" in missing:
show_reconnect_prompt("follower and like counts")
The last 3 lines are the part that saves support tickets. A follower count of 0 because a scope was declined looks identical to a creator with no followers. Showing a reconnect prompt instead tells the user something true and gives them a way to fix it.
Which scopes does your product need?
| What you are building | Scopes | Products to add |
|---|---|---|
| Creator profile display | user.info.basic, user.info.profile | Login Kit |
| Analytics or media kit | user.info.basic, user.info.profile, user.info.stats, video.list | Login Kit |
| Scheduling tool, direct posting | Above plus video.publish | Login Kit and Content Posting API |
| Review and approval workflow | Above plus video.upload | Login Kit and Content Posting API |
| Creator sign-in only | user.info.basic | Login Kit |
| Academic research | research.data.basic | Research API, institutional eligibility required |
| User data import | A portability.* scope matched to the data category | Data Portability API |
Request the smallest set that your product visibly uses. Over-requesting slows the audit, and on TikTok it also increases the chance a user declines part of the request at the consent screen, which puts you straight back into partial grant handling.
What does no scope unlock?
3 things, and none of them are permission problems. No approval widens any of them.
| What you cannot get | Why |
|---|---|
| Audience demographics | TikTok's native developer API does not return age, gender or location breakdowns for a creator's audience. There is no scope for it |
| Data on a creator who has not authorised your app | Every user.info.* and video.* scope is scoped to the authorising user. Nothing in this list reaches a third party |
| Commercial use of Research API data | The Research API is limited to qualifying institutions, and its terms do not permit commercial product building |
The first row is the one that reshapes roadmaps. If your product promises audience demographics on TikTok, the native API is not the route, and no amount of scope approval changes that. We set out where that boundary sits across platforms in authenticated versus public social data.
What are the most common scope mistakes?
- Assuming you were granted what you requested. The most common and the most avoidable. Read the
scopefield on every token. - Requesting a field without its scope. The call fails rather than returning null, so a single unscoped field in your
fieldsparameter breaks the whole request. - Confusing video.upload with video.publish. 1 puts a draft in the creator's inbox, the other posts to their profile.
- Adding Content Posting API before Login Kit. It is a prerequisite, and the portal will not let you skip it.
- Keying on open_id across several apps. Use
union_idif you need to recognise the same creator in more than 1 of your products. - Testing only in sandbox. Only your registered target users can connect, and published content is forced private until the production audit passes.
Where does Phyllo fit?
We run this layer for you. When a creator connects their TikTok account through your product, Phyllo's TikTok API handles the scope requests, the partial grant logic, the 24 hour token refresh cycle and the app audit, and returns normalised fields through the same schema that serves 25+ other platforms.
The audience demographics TikTok's native API does not expose are among the fields we surface for authenticated creators. Per-platform field coverage is public at getphyllo.com/coverage and the API reference needs no sales call.
Where we are not the answer: if TikTok is your only platform and you have engineering capacity, request the scopes yourself. TikTok charges nothing for the API and the documentation is solid. The case for a layer begins at the second platform, because every one of them names its scopes differently, expires its tokens differently and reviews apps differently.
The short version
Add Login Kit first, because everything else depends on it. Request the smallest scope set your product visibly uses, and remember that user.info.basic arrives by default.
Then write your integration on the assumption that you will be granted less than you asked for. Store the scope value from the token response, build your field requests from it, and show the creator a reconnect prompt when something is missing rather than a zero that looks like real data.
Want TikTok fields without running the audit, the scope logic and the 24 hour refresh cycle yourself? Get a demo
What are the TikTok API scopes?
The main read scopes are user.info.basic, user.info.profile, user.info.stats and video.list. Publishing uses video.upload and video.publish. Other families cover Research, Portability and Minis.
Can TikTok users approve only some of the scopes I request?
Yes. TikTok's documentation states users may agree to only a subset of the scopes requested. The token response carries a scope field listing what was granted, so store and check that instead.
What is the difference between video.upload and video.publish?
video.upload sends content to the creator's TikTok inbox as a draft for them to review and post. video.publish posts directly to their profile, immediately or on a schedule. Pick by workflow.
Which scope returns TikTok follower count?
user.info.stats. It returns follower_count, following_count, likes_count and video_count. Requesting those fields without that scope makes the whole call fail rather than returning empty values.
What is the difference between open_id and union_id?
open_id identifies a user within 1 application, so the same person has a different value in each of your apps. union_id persists for that user across every app under the same developer account.
Do I need approval for TikTok API scopes?
Yes, and approval is only the first of 2 gates. TikTok approves your app to request a scope, then each user must grant it at the consent screen. In sandbox, only registered target users can connect.
How long do TikTok access tokens last?
Access tokens expire after 86,400 seconds, which is 24 hours. Refresh tokens last 31,536,000 seconds, which is 365 days. Neither refreshes automatically, so you need a background refresh job.



