Douyin is TikTok's Chinese sibling, run by the same company on a separate app, a separate domain and, as it turns out, separate endpoints. On 28 September 2026 we fetched it 19 times through residential exits in Singapore, the United States and Germany. A public user page answers a plain HTTP client with 72,914 bytes and zero words from every country. Rendering it worked from Germany in 10.5 seconds, took 65 seconds from Singapore and did not finish from the United States. The endpoint that does the job needs no key at all: 2,100 bytes of JSON with the follower and like counts, identical from all three exits, 3,902 times smaller than the 8,194,019-byte render.
The keyword is proxy shopping and one claim we could test
Douyin proxies has no autocomplete. The United States SERP for it opens with Reddit threads about sending virtual gifts to a Douyin streamer through a Chinese intermediary and buying from Douyin through an agent, then two China-proxy vendor pages, a Go repository, a CDN hostname page and a tutorial for a download tool. The one result about data is a hosted-scraper listing whose first line states that a China residential exit is required because the platform refuses non-Chinese addresses. We had three non-Chinese exits available, so we measured that claim rather than repeat it.
The data intent lives under douyin scraper, which autocompletes to github, api, search, profile, video and comment, and under douyin api, which adds python, key, open api and web api. That reader wants public creator and video data for brand research, creator discovery and market monitoring in China, and this page is written for them, with the platform's own rule on crawling quoted in one line at the end.
One shell for every URL
We requested www.douyin.com/user/ followed by a 55-character sec_uid, the public profile identifier. Over plain HTTP from Singapore the response was HTTP 200, 72,914 bytes, no title, no canonical, no meta description and zero words. We then requested the discover hub at /jingxuan: 72,914 bytes. Then the same profile on the share host, iesdouyin.com/share/user/: 72,914 bytes. Three different URLs, one byte count, because the server sends the same application shell to every non-browser request and lets the client decide what to draw.
We also mined that shell for hydration state, the embedded JSON where single-page applications often keep the data before the DOM shows it. It was empty. Unlike TikTok's shell, which at least names the backend partition serving you, Douyin's shell contains nothing a parser can use. Either you run a browser, or you use a different surface.
Rendering worked from Germany and not from the United States, on the same afternoon
So we ran the browser, from three countries, on the same profile:
| Exit | No-JS words | Rendered words | Title after render | Time |
|---|---|---|---|---|
| Singapore | 0 | 17 | none | 65.1 s |
| United States | 0 | did not finish | none | page not loaded after 29.3 s |
| Germany | 0 | 20 | Dr.Wu的抖音 - 抖音 | 10.5 s |
Only the German exit produced a page with a title, an h1 carrying the nickname, a canonical and a meta description. A full render from Germany with the video grid loaded weighed 8,194,019 bytes, took 32.1 seconds and yielded 682 words and 25 cover images. That is 8.19 MB and half a minute of browser time for one profile, and it depended on which exit we happened to use. Douyin's web app is heavy and its behaviour differs by exit in ways that change hour to hour, so a browser-based Douyin job needs the exit pinned for the duration and a content-based wait, not a load event. This is the same lesson as TikTok, where the render finishes only when you wait on a selector, and the reason we do not recommend the browser as the primary path here.
The endpoint that answers without a key
The share host has an older JSON endpoint that the app's own share pages use: iesdouyin.com/web/api/v2/user/info/?sec_uid=. We called it over plain HTTP with no cookie, no token and no signature.
| Exit | Status | Bytes | Time | Content |
|---|---|---|---|---|
| Singapore | 200 | 2,100 | 2.3 s | JSON, complete |
| United States | 200 | 2,100 | 2.5 s | JSON, complete |
| Germany | 200 | 2,100 | 1.6 s | JSON, complete |
Same bytes from three continents. The object carries the nickname, the short id, the avatar URLs, mplatform_followers_count, total_favorited, following_count, aweme_count, the verification fields, is_oversea and a special_state_info block that, for this account, states in Chinese that the account is in a special state and directs the reader to the app. Three details matter:
- The counters are rounded. This profile reported 87,000 followers, 1,000 following and 1,570,200 total likes. Round figures are what the share surface serves; treat them as buckets with a timestamp, not as a time series to diff.
- The moderation state is in the data. The
special_state_infoblock is the platform telling you the account is restricted. Filter on it before you count the account as active. - The response mints a token. Every reply carried an
x-ms-tokenheader. You do not need it for this endpoint; you would for the main web API onwww.douyin.com, whose/aweme/v1/web/routes require ana_bogussignature plusmsTokenandttwidcookies according to every listing we read. For profile counters, the older share endpoint makes that machinery unnecessary.
So the hosted-scraper claim did not survive the measurement. From Singapore, the United States and Germany, with residential exits, the endpoint answered identically. A China exit may help with the main web API; it is not a precondition for reading public profile counts.
How Douyin differs from TikTok, endpoint by endpoint
| Surface | TikTok, measured 20 September | Douyin, measured 28 September |
|---|---|---|
| Profile URL | www.tiktok.com/@handle | www.douyin.com/user/ plus a 55-character sec_uid |
| Video URL | /@handle/video/id | www.douyin.com/video/ plus a 19-digit aweme id |
| Plain HTTP profile | 371,263 to 417,948 bytes, 0 words | 72,914 bytes, 0 words |
| Open endpoint | oEmbed, 668 bytes, name only, no counters | share user-info, 2,100 bytes, followers and likes |
| What the exit changes | the backend partition and API host | whether the render finishes; the endpoint does not change |
| robots.txt | 25 AI crawlers, Disallow: / | 26 named agents, six path rules, no wildcard block |
The two platforms share a parent and almost nothing else that a collector can reuse. Endpoints, identifiers, cookies and robots policy are all different, so a TikTok collector pointed at Douyin reads nothing, and a Douyin collector is a separate build.
What robots.txt and the user agreement say
douyin.com/robots.txt is 1,044 bytes and unusual in shape. There is no User-agent: * block at all. One block names 26 agents, among them Googlebot, Google-Extended, Bingbot, DuckDuckBot, Baiduspider, the Sogou family, ByteSpider and ToutiaoSpider from its own parent, PerplexityBot, Perplexity-User, OAI-SearchBot, GPTBot, ChatGPT-User and deepseekbot, and disallows six path patterns for them: /follow, user pages entered from a video, topic aggregations, general search, any URL with enter_from= and any URL with vid=. Bingbot is additionally kept out of modal URLs, and Baiduspider out of /video/, /note/, /shipin/, /zhuanti/, /topic/ and /search/. Everything else, for everyone, is unaddressed. The sitemap it points to is 2,030 bytes and lists twelve corporate pages, none of them content.
The user agreement is more direct than the robots file. Clause 2.4 states that, without the platform's prior express written authorisation, you may not use Douyin in any unauthorised form, and it lists adaptation, copying, distribution, crawling, vertical search, mirroring and trading by name. That is the one line to read before scaling anything on this platform, and we do not help with account automation, engagement or anything on the logged-in side of it.
What it costs, and what to stop paying for
Every number came through residential proxies on the Basic line at $0.80/GB, counting a gigabyte as 10^9 bytes:
| Job | Bytes per request | Requests per GB | Cost per request |
|---|---|---|---|
| Profile counters, share endpoint, plain HTTP | 2,100 | 476,190 | $0.0000017 |
| User page, plain HTTP (shell only) | 72,914 | 13,715 | $0.000058 |
| User page, rendered from Germany | 8,194,019 | 122 | $0.0066 |
One thousand profiles cost 2.1 MB and about a fifth of a cent through the endpoint, against 8.19 GB and $6.56 rendered, before browser time and before the renders that never finish. On mobile proxies at $2.30/GB the endpoint call is $0.000005 and the render $0.019; nothing we measured examined the network type, so the cheaper line is the one to buy. When the browser does lock you out of a site entirely, the pattern is documented across twelve targets in the headless browser locks you out; on Douyin it is not a lockout, it is a cost.
The setting that works on Douyin
- Network: residential, Basic line at $0.80/GB. The endpoint returned the same 2,100 bytes from Singapore, the United States and Germany; the network is not what decides the outcome.
- Fetch mode:
engine: tls, plain HTTP, againstiesdouyin.com/web/api/v2/user/info/?sec_uid=. The web page over plain HTTP is 0 words; rendered it is 682 words for 8,194,019 bytes and only from the exit that hydrates. - Country: any exit for the endpoint. If you must render, pin the exit that finished for you and keep it for the job: on 28 September that was Germany at 10.5 seconds, while Singapore took 65.1 seconds and the United States did not finish in 29.3.
- When the proxy is not enough: to discover video URLs by topic without touching Douyin's search, our video search collector returned 10 douyin.com/video/ rows with title, date and duration in 4.75 seconds, and each aweme id it returns is the key to the video and comment surfaces. For the rendered profile grid, the web scraping API with rendering is $0.001 per page.
- Every account gets $2 of free API usage per month.
For the platform that behaves the opposite way, where the exit changes nothing and the note text ships in the head, read Xiaohongshu; for a public API that answers identically from every continent and needs no signature, Bilibili.