Home > Blog > What Is a TikTok secUid and How Do You Get One?
User Data

TikTok secUid Explained: What It Is and How to Get One

By PrimeApi·August 15, 2026·7 min read·Updated August 15, 2026

TikTok identifies the same account in three different ways, and picking the wrong one is the most common reason a first API integration returns nothing. There is the public @handle people type into the app, a numeric user ID buried in the profile payload, and a long opaque string called the secUid. They are not interchangeable, they are not derivable from each other, and different endpoints insist on different ones. This post explains what each identifier is, which is stable enough to key a database on, which endpoint expects which, and how to turn a handle into a secUid in a single call.

The three identifiers

The @handle

The handle is the human-facing name - taylorswift in tiktok.com/@taylorswift. In API responses it comes back as user.uniqueId. It is the only identifier a person can type from memory, which makes it the natural entry point for a search box or a CSV of accounts to track. It is also the only one a creator can change. Renaming an account rewrites the handle while everything else about the account stays put, so a database that keys rows on the handle silently splits one creator into two records the day they rebrand.

The numeric user ID

Every account also carries a numeric ID, returned as user.id - a digit string like 6881290705605477381. It is assigned once and does not follow renames. Of the working endpoints, this is what user-followers expects in its userid parameter. Note it is long enough to overflow a 32-bit integer and, in some JSON parsers, to lose precision as a float, which is exactly why the API returns it as a string. Keep it a string end to end.

The secUid

The secUid is the one people trip over. It is a long URL-safe string that starts with MS4wLjABAAAA and runs roughly seventy-six characters, for example MS4wLjABAAAAqB08cUbXaDWqbD6MCga2RbGTuhfO2EsHayBYx08NDrN7IE3jQuRDNNN6YwyfH6_6. It appears in the profile record as user.secUid. It is not an encoding of the numeric ID, it is not something you can construct yourself, and there is no supported way to reverse it into anything meaningful. The only correct handling is to fetch it, store it whole, and send it back verbatim. It is also the identifier that TikTok's own profile-feed calls use internally, which is why the endpoints that mirror a profile tab - uploads, likes, playlists, reposts - all ask for it.

Comparison at a glance

IdentifierResponse fieldLooks likeSurvives a rename?Primary use
@handleuser.uniqueIdtaylorswiftNoHuman input, display, entry-point lookups
Numeric user IDuser.id6881290705605477381YesDatabase primary key, user-followers
secUiduser.secUidMS4wLjABAAAA...YesProfile feed endpoints (posts, likes, playlists, reposts)

The practical rule that falls out of this table: accept handles at the edge of your system, resolve them once, and store both the numeric ID and the secUid. Everything downstream should read from your stored identifiers, never from a handle a user typed three weeks ago.

Resolving a handle to a secUid in one call

A single request to userinfo-by-username returns all three identifiers together. The endpoint takes one required parameter, username, which is the handle without the @. Authentication is the X-PrimeAPI-Key header, and the base URL is https://api.primeapi.co/.

curl

curl -s "https://api.primeapi.co/userinfo-by-username?username=taylorswift" \
  -H "X-PrimeAPI-Key: YOUR_API_KEY"

Node.js (Axios)

const axios = require("axios");

async function resolveHandle(username) {
  const res = await axios.get(
    "https://api.primeapi.co/userinfo-by-username",
    {
      params: { username },
      headers: { "X-PrimeAPI-Key": "YOUR_API_KEY" }
    }
  );
  const u = res.data.user;
  console.log("Credits left:", res.headers["x-primeapi-balance"]);
  return {
    handle: u.uniqueId,
    userId: u.id,
    secUid: u.secUid,
    nickname: u.nickname,
    verified: u.verified,
    followers: res.data.stats.followerCount
  };
}

resolveHandle("taylorswift")
  .then(ids => console.log(ids))
  .catch(err => console.error(err.response ? err.response.data : err.message));

Python (Requests)

import requests

HEADERS = {"X-PrimeAPI-Key": "YOUR_API_KEY"}

def resolve_handle(username):
    r = requests.get(
        "https://api.primeapi.co/userinfo-by-username",
        params={"username": username},
        headers=HEADERS,
        timeout=15,
    )
    r.raise_for_status()
    u = r.json()["user"]
    return {
        "handle": u["uniqueId"],
        "user_id": u["id"],
        "sec_uid": u["secUid"],
        "nickname": u["nickname"],
        "private": u["privateAccount"],
    }

if __name__ == "__main__":
    print(resolve_handle("taylorswift"))

What else the profile call gives you

Since you are spending the credit anyway, take everything the payload offers. The response splits into a user object and a stats object.

FieldTypeNotes
user.idstringNumeric user ID, returned as a string
user.uniqueIdstringThe @handle
user.secUidstringThe opaque profile-feed identifier
user.nicknamestringDisplay name
user.signaturestringBio text
user.verifiedboolVerification badge
user.privateAccount, user.secretboolWhether the feed endpoints will return anything
user.avatarThumb, avatarMedium, avatarLargerstringAvatar URLs at three sizes
user.createTimeintAccount creation timestamp
user.bioLink.linkstringLink in bio, when one is set
stats.followerCount, followingCount, heartCount, videoCount, diggCountintHeadline counters

Reading user.privateAccount here saves calls later: a private profile will not hand you a post list no matter which identifier you send. The full breakdown of this payload is in the walkthrough on how to get TikTok user data via the API, which uses the same single call.

Spending the secUid: user-posts

Now that you hold the secUid, user-posts becomes available. It requires secUid and accepts count and cursor for paging.

curl -s -G "https://api.primeapi.co/user-posts" \
  --data-urlencode "secUid=MS4wLjABAAAAqB08cUbXaDWqbD6MCga2RbGTuhfO2EsHayBYx08NDrN7IE3jQuRDNNN6YwyfH6_6" \
  --data-urlencode "count=35" \
  --data-urlencode "cursor=0" \
  -H "X-PrimeAPI-Key: YOUR_API_KEY"

Two details about this response catch people out. First, the payload is wrapped: the videos live at data.itemList, not at the top level, and data.cursor and data.hasMore sit beside them. Second, data.cursor comes back as a string - values such as "1713553237000" - so pass it back exactly as received rather than casting it to a number. Loop while data.hasMore is true, feeding the previous cursor into the next request.

Each entry in data.itemList carries the video's id, its caption in desc, an upload createTime, plus author, authorStats and music blocks and flags including isAd, privateItem, secret, collected, digged, duetEnabled, shareEnabled and itemCommentStatus. The response also repeats data.statusCode, data.status_code and data.status_msg, and an extra.logid value that is worth logging when you need to report a bad response. Paging the whole back catalogue is covered step by step in the guide to getting every video from a TikTok user.

Which endpoint wants which identifier

EndpointRequired identifierParameter
userinfo-by-username@handleusername
user-postssecUidsecUid
user-liked-postssecUidsecUid
user-playlistsecUidsecUid
user-repostsecUidsecUid
user-followersNumeric user IDuserid

That last row is the mix-up worth memorising: four profile-feed endpoints want the secUid, while the follower listing wants the numeric ID. Sending a secUid where a userid belongs does not throw a helpful error - you simply get nothing useful back, and the credit is still spent. The follower side is walked through separately in the post on fetching a TikTok follower list, and the likes tab in reading a user's liked videos.

Storing identifiers sensibly

A few habits keep this from becoming a maintenance problem:

  • Key on the numeric ID. Make user.id your primary key and store the handle as a mutable display attribute alongside it.
  • Cache the secUid, refresh the stats. The identifiers are stable, the counters are not. Resolve a handle once, then hit the feed endpoints directly on later runs instead of paying a credit to re-resolve.
  • Keep the full string. Give the secUid column enough room - a hundred characters or more - and never trim it.
  • URL-encode on the way out. The value is URL-safe in practice, but encoding it is free insurance, which is what the --data-urlencode flag and the params arguments above are doing.
  • Handle re-resolution. If a stored secUid stops returning posts, run the handle through userinfo-by-username again before assuming the account is gone.

Credits, limits and errors

Each call costs 1 credit, whichever endpoint it hits, and your remaining balance comes back in the X-PrimeAPI-Balance response header. New accounts start with 50 free credits, which is plenty to resolve a batch of handles and confirm the identifier flow works before paying anything. The default rate limit is 100 requests per minute; responses are fetched live with no caching, averaging around a second. If a call fails, branch on the JSON message: "Please sign up to primeapi.co" means no key header was sent, "PrimeAPI-Key is not available" means the key does not match an active account, and the per-minute and "Your balance has been exhausted..." messages cover the two quota cases. You can try any of these endpoints against your own key in the API playground before writing code, and the parameter reference for each one lives in the documentation. Credit bundles start at $9.90 for 2,500 requests on the pricing page.

Summary

Three identifiers, one workflow. The handle is what humans give you and the only one that can change. The numeric ID is your database key and what user-followers expects. The secUid is the opaque string the profile-feed endpoints require, and one call to userinfo-by-username hands you all three at once. Resolve early, store both stable identifiers, and the rest of the User category stops throwing empty responses at you. PrimeApi is an independent service and is not affiliated with or endorsed by TikTok or ByteDance.

Frequently asked questions

What is a TikTok secUid?

The secUid is an opaque string TikTok attaches to every account, separate from the @handle and from the numeric user ID. It is the identifier the profile-feed endpoints expect, so user-posts, user-liked-posts, user-playlist and user-repost all take a secUid rather than a username. In live responses it is a long URL-safe string beginning with MS4wLjABAAAA.

Is the secUid the same thing as the numeric user ID?

No. They are two different values returned side by side in the same profile record. The numeric ID is a short digit string such as 6881290705605477381 and appears as user.id. The secUid is a long alphanumeric string and appears as user.secUid. Some endpoints accept one and some accept the other, so store both.

How do I get a secUid from a username?

Call userinfo-by-username with the handle and read user.secUid from the response. That is a single request, costs 1 credit, and also hands you user.id, user.nickname and the follower, heart and video counts in the same payload, so there is no reason to make a second call just for the identifier.

Does a secUid change over time?

Handles change whenever a creator renames an account, which is what breaks most pipelines keyed on @names. The secUid and the numeric ID stayed constant across every account we re-checked, so they are the safer database keys. Treat both as opaque strings and re-resolve a stored identifier if a call ever comes back empty.

Can I decode a secUid or build one myself?

Treat it as opaque. Do not parse it, do not try to derive it from the numeric ID, and do not truncate it for storage. Store the full string exactly as returned and URL-encode it when you place it in a query string.

Which identifier do the follower endpoints use?

user-followers takes the numeric ID in its userid parameter, not the secUid. This is the single most common mix-up: the posts endpoints want secUid and the follower listing wants the numeric ID, so a workflow that saves only one of the two will fail on half its calls.

Start building with the PrimeApi TikTok API
50 free credits when you sign up. No card required - you only pay when you need more.

← Back to the PrimeApi Blog