Troubleshooting
The handful of things that trip people up, and how to fix each one.
Most of these come down to network reality or how Douyin serves its data, not a bug.
A command exits 4 (walled)
This is the common one. Douyin serves its signed aweme/v1/web/* API and its
video and user web pages behind an anti-bot layer that scores the caller's IP,
region, and session.
- The signed endpoints (
video,user,posts,comments,search) return an HTTP 200 with an empty body from a non-China or datacenter IP. There is no JSON error and no data, just nothing. - The video and user web pages return a JavaScript challenge shell (the
__acchallenge, markers__ac_nonceand__ac_signature) with no embedded data, so there is no server-rendered fallback to read. - The non-realtime billboard tabs (
--tab video|music|star) are walled the same way: an empty list, or a server error code on the music tab.
When douyin sees one of these signals it exits 4 (needs auth) with a message
that the surface needs a residential session, rather than pretending it found
nothing or printing the challenge page as data. The endpoints, request shapes,
and parsers are correct; the data is real and reachable, just not from where you
are calling. Run the command from a China IP or a warm browser session, or stick
to douyin hot (the realtime word billboard), which answers from anywhere.
The wall is at the IP, region, and JavaScript-challenge layer, not in the code, so there is no key or token the client could send to open it.
A genuinely empty result (exit 3) versus a wall (exit 4)
douyin distinguishes the two. A successful request that simply found no items
exits 3 (no results). A blocked request, where the server returned an empty body
or a challenge, exits 4 (needs auth). A specific id that does not exist exits 6
(not found). Check the exit code in scripts to tell them apart.
Requests start failing or returning 429
Douyin rate-limits like any public site. douyin already paces requests and
retries the transient failures, but a hard limit still means backing off. Raise
the delay between requests with --rate (for example --rate 1s) and retry
later. A burst of 429 or 5xx responses is the site asking you to slow down, not
a defect. A 429 after retries exits 5 (rate limited).
Seeing exactly what the API returned
When a command exits 4 and you want to see the body for yourself, use the raw
escape hatch:
douyin raw https://www.douyin.com/aweme/v1/web/aweme/detail/?aweme_id=7106594312292453675
It prints the endpoint's body untouched, including an empty body when walled, so
you can confirm the wall rather than guess. Add -v for per-request detail on
any command.
The binary is not on your PATH
go install puts the binary in $(go env GOPATH)/bin (usually ~/go/bin), and
a release archive leaves it wherever you unpacked it. If your shell cannot find
douyin, add that directory to your PATH. See
installation.