DEV Community

Hassan
Hassan

Posted on

How I Blocked 90% of Bot Requests on My Free TikTok Downloader Using Cloudflare Turnstile and PHP

I launched TikRapid — a free TikTok video downloader — and within the first few days the API was getting hammered. Not by real users. By bots.
The problem with free download tools is obvious in hindsight. No login means no friction. No friction means bots can hit your endpoint thousands of times a minute. My API costs were climbing fast and real users were getting timeout errors because the server was busy processing junk requests.
I needed bot protection that did not break the user experience. No login walls. No annoying CAPTCHAs that make people give up halfway through. Something invisible to real users but effective against automated traffic.
Cloudflare Turnstile was the answer.

What Turnstile actually does differently

Most CAPTCHA systems make the user do something — click a checkbox, identify traffic lights, type distorted text. Turnstile runs a challenge in the background using browser signals, interaction patterns and device fingerprinting. A real user on a real device passes automatically in most cases. A bot fails silently.
For a tool like TikRapid where the whole point is speed and simplicity, this mattered a lot. Adding a visible CAPTCHA would have killed the experience. Turnstile kept it clean.

The implementation

The frontend loads the Turnstile widget and executes the challenge when the user clicks Download. On success it fires a callback that passes the token to my PHP backend along with the TikTok URL.
On the server side the first thing my API handler does — before anything else — is verify that token with Cloudflare's siteverify endpoint.
The verification is a simple POST request. Cloudflare returns a JSON response with a success boolean. If it fails the request stops there. The TikTok URL never gets processed. No API call gets made. No server resources get used.
This is the key architectural decision. Putting Turnstile verification as the absolute first step in the handler means failed verifications cost almost nothing. The only processing that happens is one HTTP request to Cloudflare's endpoint. Everything expensive — the URL parsing, the cURL request to the download API, the JSON parsing — only runs after verification passes.

The URL cleaning problem

One thing Turnstile did not solve was dirty URL input. Real users paste TikTok links in all kinds of formats. The share sheet on iPhone sometimes adds extra text around the URL. Some users paste the full page URL with query strings. Some paste shortened vt.tiktok.com links.
I added a regex extraction step that pulls the clean TikTok URL out of whatever the user pastes. It handles the main domain variations — www, vt, vm, m — and strips trailing punctuation that sometimes gets included when people copy from message threads.
After extraction I run it through PHP's filter_var with FILTER_VALIDATE_URL and a domain check before anything else happens. Bad input gets rejected immediately with a clear error message.

What the numbers looked like

Before Turnstile the server logs were full of rapid-fire identical requests from the same IP ranges. After implementing it those dropped off almost completely within 24 hours. Real user requests continued normally. The API timeout errors that real users were hitting went away because the server was no longer busy processing bot traffic.
The drop was significant enough that I wish I had added it before launch rather than after.

Hosting setup context

TikRapid runs on PHP on Hostinger with DNS routed through Cloudflare. The Cloudflare layer handles DDoS protection and caching at the edge before requests even reach Hostinger. Turnstile sits on top of that as an application-level check. Between the two layers the server only sees traffic that has passed both network-level and application-level verification.

One thing I would do differently

My current implementation soft-fails if the Turnstile token is missing — it logs the error but lets the request continue. This was a temporary decision during testing that I never went back and hardened. In production you should hard-fail on a missing token. If there is no token the request did not come through your frontend and should not be processed.
That is the one gap in the current setup. Everything else has held up well.

If you are building a free tool with a public API endpoint

Add Turnstile before you launch. The free tier covers most use cases. Implementation is straightforward — a script tag on the frontend, one POST request on the backend, one boolean check. The time investment is small and the protection is immediate.
For anyone curious about how the download side works — the tool fetches the source video file before TikTok's app layer applies the watermark overlay. The watermark is client-side rendering, not part of the stored asset. That is a separate topic but Marcus Webb covered the creator-facing side of it well on Medium if you want the non-technical angle.

You can see the Turnstile implementation
running live at tikrapid.com.

webdev #php #showdev #productivity

Top comments (0)