About

Bot Blocking Isn't One Header — Five Layers, Seen from the Site's Side

Connection, request, page, input and session are checked for one consistent story, then scored

When I heard Reddit and Naver were keeping browser-driving AI out, my first guess was "they check the User-Agent header." Looking into it, that's not it. Modern bot management doesn't look at one header; it checks whether signals from several layers agree, and scores the request. This is written from the site operator's side, the side doing the blocking. It shows what to decide first when you add bot protection to your own service.

The picture people imagine, and the real one

imagined:  request ── User-Agent ──▶ allow / block

In practice the front end looks at several layers. The figure follows the structure Cloudflare documents publicly; other providers may differ.

1 ConnectionTLS ClientHello fingerprint, HTTP/2 settings 2 Requestheader order, client hints, sec-fetch-* UA 3 Page scriptautomation and headless traces 4 Inputare clicks and keys real input? 5 SessionIP reputation, pacing, account history score 1–99 low = likely automated allow · challenge · block changing User-Agent touches only the small UA box in layer 2
Layer What it looks at Signal for the defender
Connection TLS ClientHello fingerprint, HTTP/2 settings script HTTP clients and real browsers differ from here on
Request header set and order, client hints, sec-fetch-* if the UA names one browser and other headers point to another, the mismatch is a signal
Page the browser environment as seen from JavaScript traces of headless or automation tools
Input whether clicks and keys are real input events generated by scripts
Session IP reputation, request pacing, account history behavior adds up even if each request looks clean

Changing the User-Agent touches one cell in the second row. If the other layers tell a different story, the score stays.

Scores run from 1 to 99

Per Cloudflare's bot score docs, scores go from 1 to 99, and lower means more likely automated. The engines are heuristics (matching known fingerprints), machine learning, and JavaScript detections. A request the heuristics are sure about gets a 1.

The best-known connection-layer signals are TLS fingerprints like JA3 and JA4. JA4 improves on JA3 by sorting the ClientHello extensions. Granular scores and JA3/JA4 values are visible only to Enterprise customers who bought Bot Management; Pro and above see grouped "automated / human" buckets.

Passing once isn't the end. In an August 2026 blog post Cloudflare described detection that watches client behavior for the whole session. A CAPTCHA guards a moment; a behavior score watches what comes after.

Reddit narrowed the doors, not the headers

As reported by The Verge (2026-09-30), Reddit's explanation: Old Reddit requires login and keeps only accounts active within the six months before the switch. RSS ends on 2026-11-13. The stated reason is large-scale scraping and automated abuse.

That isn't "filter the AI browser header." It's closing doors and narrowing accounts. From the defender's side it's the cheapest move. The fingerprint race never ends; closing an anonymous entry point is done once.

For Naver I found no public document saying "this header means an agent browser." Yeti is the name of Naver's outbound crawler, not a marker for filtering incoming browsers. I couldn't confirm which layer Naver uses, so I'm not claiming one.

For your own service: what, and when

Situation Do this first
automated attempts flood login or sign-up rate limits and a CAPTCHA
someone scrapes your public API or RSS move it behind auth, or issue keys
browser automation posing as people take the front-end bot score (Cloudflare etc.) and write rules on it

In Rails, the first row starts with one line in a controller: rate_limit, available since Rails 7.2.

class SessionsController < ApplicationController
  rate_limit to: 10, within: 3.minutes, only: :create
end

A User-Agent blocklist alone guards the weakest cell. It's useful for sorting out crawlers that honestly say who they are. Anyone trying to hide changes that cell first.

What I didn't do: I didn't send automated browsers to Reddit or Naver to see which layer rejects them, and the score weights aren't public.

If you're deciding how much bot and scraping protection your service needs, or how to split login and API entry points, ask us at https://www.negabaro.com/contact.

How It Works

1

Connection: TLS ClientHello and HTTP/2 settings reveal the client type

2

Request: check that header order and client hints agree with the UA

3

Page and input: JavaScript checks the environment and the events

4

Session: IP, pacing and account history add up to a 1-99 score: allow, challenge or block

← Why a Tokyo Camera Landed on Our Saitama Map — The Real Cost of a Map Service Is the Coordinates