Preliminary Checks
Reproduction
https://github.com/jakvbs/clerk-localhost-handshake-repro/tree/0f56bb5332dbde96ed3911c6b220e2b4c6b5ac7c
Publishable key
pk_test_aGVscGVkLW95c3Rlci01Ny5jbGVyay5hY2NvdW50cy5kZXYk
Description
A cold guest navigation to a public page on plain HTTP localhost repeatedly enters Clerk's development-browser handshake path. The reproduction is a fresh, standalone Next.js App Router application containing only ClerkProvider, clerkMiddleware, one public page, and a Playwright measurement. It has no application business logic, database, login flow, testing tokens, or mocks.
Steps to reproduce:
-
Clone the reproduction at the exact commit linked above.
-
Copy .env.example to .env.local and provide the included development instance's publishable and secret keys locally. The secret key is not committed or included in this report.
-
Install and build:
bun install --frozen-lockfile
bunx playwright install chromium
bun run build
-
Run five fresh-browser-context repetitions:
bun run test:repro -- --repeat-each=5
The command is expected to exit with code 1 when the bug reproduces because the final assertion requires at most one handshake; the page itself still reaches HTTP 200.
Expected behavior:
One cold guest navigation to / should reach the public page with at most one /v1/client/handshake document request.
Actual behavior:
The problem reproduced in 5/5 fresh Chromium contexts. Every single page.goto("/") produced:
- exactly 3 document requests whose pathname was
/v1/client/handshake;
- 9 HTTP 307 document responses;
- a final HTTP 200 response on
/.
The Node-observed redirect-prefix durations were 1087, 729, 704, 748, and 710 ms (median 729 ms). The corresponding navigation-to-load durations were 1287, 934, 890, 940, and 902 ms (median 934 ms). These are observations from this machine, not a latency benchmark or a claim that any particular change guarantees an improvement.
The responses set __clerk_db_jwt with SameSite=None and without the Secure attribute. The missing Secure attribute is a measured response fact. A browser refusing to persist or return that cookie and thereby causing the repeated handshake is a causal hypothesis, not established by this reproduction. Likewise, this report does not claim that HTTPS would fix the issue.
The test records only sanitized URL origins/pathnames, statuses, Clerk header names, cookie names/attribute names, request counts, and monotonic timings. Raw Playwright traces remain ignored and are not published.
Environment
System:
OS: macOS 26.6.2
CPU: (8) arm64 Apple M2
Binaries:
Node: 24.14.1
npm: 11.19.1
bun: 1.4.0
Browsers installed on the host:
Chrome: 152.0.7977.83
Edge: 153.0.4234.32
Firefox: 155.0.1
Safari: 26.6.2
Browser used by the verified Playwright run:
Chromium: 151.0.7922.34
npmPackages (pinned to match the application where the behavior was observed; not claimed to be latest):
@clerk/nextjs: 7.7.6
@clerk/backend override: 3.16.6
@clerk/react override: 6.14.3
@clerk/shared override: 4.29.1
@playwright/test: 1.62.1
next: 16.3.1
react: 0.0.0-experimental-eafeac09-20260819
react-dom: 0.0.0-experimental-eafeac09-20260819
typescript: 7.0.2
Preliminary Checks
clerk/javascriptissues forDevBrowserMissing, repeated localhost handshakes,__clerk_db_jwt, andSameSite/Securecombinations.Reproduction
https://github.com/jakvbs/clerk-localhost-handshake-repro/tree/0f56bb5332dbde96ed3911c6b220e2b4c6b5ac7c
Publishable key
pk_test_aGVscGVkLW95c3Rlci01Ny5jbGVyay5hY2NvdW50cy5kZXYk
Description
A cold guest navigation to a public page on plain HTTP localhost repeatedly enters Clerk's development-browser handshake path. The reproduction is a fresh, standalone Next.js App Router application containing only
ClerkProvider,clerkMiddleware, one public page, and a Playwright measurement. It has no application business logic, database, login flow, testing tokens, or mocks.Steps to reproduce:
Clone the reproduction at the exact commit linked above.
Copy
.env.exampleto.env.localand provide the included development instance's publishable and secret keys locally. The secret key is not committed or included in this report.Install and build:
Run five fresh-browser-context repetitions:
The command is expected to exit with code 1 when the bug reproduces because the final assertion requires at most one handshake; the page itself still reaches HTTP 200.
Expected behavior:
One cold guest navigation to
/should reach the public page with at most one/v1/client/handshakedocument request.Actual behavior:
The problem reproduced in 5/5 fresh Chromium contexts. Every single
page.goto("/")produced:/v1/client/handshake;/.The Node-observed redirect-prefix durations were 1087, 729, 704, 748, and 710 ms (median 729 ms). The corresponding navigation-to-load durations were 1287, 934, 890, 940, and 902 ms (median 934 ms). These are observations from this machine, not a latency benchmark or a claim that any particular change guarantees an improvement.
The responses set
__clerk_db_jwtwithSameSite=Noneand without theSecureattribute. The missingSecureattribute is a measured response fact. A browser refusing to persist or return that cookie and thereby causing the repeated handshake is a causal hypothesis, not established by this reproduction. Likewise, this report does not claim that HTTPS would fix the issue.The test records only sanitized URL origins/pathnames, statuses, Clerk header names, cookie names/attribute names, request counts, and monotonic timings. Raw Playwright traces remain ignored and are not published.
Environment
System: OS: macOS 26.6.2 CPU: (8) arm64 Apple M2 Binaries: Node: 24.14.1 npm: 11.19.1 bun: 1.4.0 Browsers installed on the host: Chrome: 152.0.7977.83 Edge: 153.0.4234.32 Firefox: 155.0.1 Safari: 26.6.2 Browser used by the verified Playwright run: Chromium: 151.0.7922.34 npmPackages (pinned to match the application where the behavior was observed; not claimed to be latest): @clerk/nextjs: 7.7.6 @clerk/backend override: 3.16.6 @clerk/react override: 6.14.3 @clerk/shared override: 4.29.1 @playwright/test: 1.62.1 next: 16.3.1 react: 0.0.0-experimental-eafeac09-20260819 react-dom: 0.0.0-experimental-eafeac09-20260819 typescript: 7.0.2