A toolkit for testing the maximum cookie (HTTP header) size a web server will accept.
It consists of two parts:
cookietester.sh— a portable bash script (macOS & Linux) that injects a test cookie of a chosen size into a cURL request and reports whether the server accepts or rejects it.size-server.js— a small Node.js server that inspects incoming requests, logs their size, and returns proper HTTP status codes for oversized headers/bodies.
- bash 3.2+ (macOS-compatible — uses only bash 3.2-safe syntax, no bash 4+ features)
- Standard tools:
curl,xargs,sed,grep,head,tr,file,bc,mktemp
Check your bash version:
bash --version- Node.js
Make it executable (one time only):
chmod +x cookietester.shRun it:
./cookietester.sh request.txt # read cURL command from a file (recommended)
./cookietester.sh # interactive paste (small commands only)Or run directly through bash (no chmod needed):
bash cookietester.sh request.txtModes:
- Manual — you pick the cookie sizes to try. On success it can save the downloaded file with the correct extension and open it.
- Auto-bisect — automatically finds the server's limit by ramping up, then binary-searching the cookie size.
The test cookie is sent as a raw
Cookieheader via-H "@<header-file>", bypassing curl's cookie engine so the server's real limit is tested. Reading the cookie from a file also avoidsARG_MAX.A curl exit code
55/52at large sizes means the server closed the connection because the header was too large — this is correct behavior, not a bug.
Always start the server with --max-http-header-size so large headers/cookies reach the app code and get a proper 431 instead of a raw parser abort:
node --max-http-header-size=5242880 size-server.js # 5 MB (5 * 1024 * 1024)With PM2:
pm2 start size-server.js --name size-server \
--node-args="--max-http-header-size=5242880"There are three layers of limits that can cause a cookie test to fail at different stages:
| Layer | Enforced by | Default | Result on overflow |
|---|---|---|---|
| 1 | cURL client (outgoing headers) | ~1 MB | curl: (100) — use nc instead |
| 2 | Node parser (--max-http-header-size) |
16 KB | 431 on overflow |
| 3 | Server code (custom checks) | 5 MB | 431 (header) / 413 (body) |
- Headers (including cookies) are limited by Node's parser before your request callback runs. Exceeding it aborts with
HPE_HEADER_OVERFLOW. - Body has no Node default — the server enforces a custom 5 MB limit via streaming and aborts early.
cURL 8.x enforces an internal ~1 MB cap on outgoing request headers. When exceeded you'll see:
curl: (100) HTTP request too large
HTTP_STATUS:000|CTYPE:|SIZE:0
This means the request never left cURL — raising Node's --max-http-header-size won't help.
Check your version:
curl --versionWorkaround — use nc (netcat) to send raw bytes with no client-side limit:
# ~4 MB cookie (should PASS if header limit >= ~4 MB)
{
printf 'GET / HTTP/1.1\r\n'
printf 'Host: localhost:3001\r\n'
printf 'Connection: close\r\n'
printf 'Cookie: a='
head -c 4000000 /dev/zero | tr '\0' 'A'
printf '\r\n\r\n'
} | nc localhost 3001
# ~6 MB cookie (should be REJECTED with 431)
{
printf 'GET / HTTP/1.1\r\n'
printf 'Host: localhost:3001\r\n'
printf 'Connection: close\r\n'
printf 'Cookie: a='
head -c 6000000 /dev/zero | tr '\0' 'A'
printf '\r\n\r\n'
} | nc localhost 3001Watch the server terminal for the size report (accepted) or the 431 rejection (over the limit).
| Condition | Status |
|---|---|
| Oversized headers/cookies | 431 Request Header Fields Too Large |
| Oversized body | 413 Payload Too Large |