Skip to content
douyin

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 __ac challenge, markers __ac_nonce and __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.