Incognito tab feature testing, the version that admits where it lies.
Most pages on this topic stop at "open a private window, click around, you are now a fresh visitor." That is true enough to ship most tests with, and quietly wrong in five ways that will fool you if you keep testing for long enough. This guide is the concrete recipe, the column-by-column accounting of what survives the close button, and the small list of cases where private mode is the wrong tool entirely.
Open the page in a private window (Cmd+Shift+N on Chrome, Edge, Brave, and Arc; Cmd+Shift+P on Firefox and Safari; swap Cmd for Ctrl on Windows and Linux), navigate to the feature, and exercise the flow. Incognito clears cookies, localStorage, sessionStorage, and the HTTP cache for the lifetime of the private session, so the site reads you as a first-time visitor without any logout step. It does not change your IP, your TLS fingerprint, or extension state if you opted-in extensions for private windows; plan around those before you trust the test result.
What private mode actually does, line by line
Browsers describe private mode in marketing-friendly language ("your activity won't be saved") that hides the engineering. The accurate version is more useful for testing: a private window opens a separate session-scoped storage partition. Cookies, Web Storage, IndexedDB writes, and HTTP cache entries created in that window live in that partition. When the last private window in the session closes, the partition is destroyed.
Two consequences fall out of that model. First, opening a second private window from the same browser does not give you a second clean partition; it joins the existing private session and shares storage with the first window. If you want two truly independent fresh visitors at the same time, you need two different browsers, two different profiles, or two different machines. Second, a long-lived private session that you forget to close accumulates cookies and storage just like a regular session would; only the close-window event resets it. People who leave incognito open for a day and assume each new tab is fresh are testing wrong.
The honest mental model is "a temporary parallel browser instance", not "a clean room every time you open a tab".
What a private window clears, and what it leaves on the floor
Two columns. Left, things you can rely on private mode to wipe between sessions. Right, things people assume it wipes that it does not. The right column is where every flaky test lives.
Cleared on private session close
- ✓Cookies set during the private session
- ✓localStorage and sessionStorage written by any visited page
- ✓HTTP cache entries (documents, scripts, images, fonts) fetched in the session
- ✓IndexedDB databases created during the session
- ✓Form autofill entries you typed into private windows
- ✓Site permissions granted in the session (camera, mic, location)
- ✓ServiceWorker registrations created in the session (most browsers)
- ✓Browsing history and the URL bar autocomplete from the session
Survives the close button
- ×Your IP address and the network path the request takes
- ×Your TLS fingerprint, OS user agent, and any device-fingerprinting signals
- ×Extensions enabled for private mode (off by default, but easy to flip on)
- ×Bookmarks added during a private session in some browsers
- ×Files downloaded to the regular Downloads folder
- ×BFCache snapshots within the same private session, when you click back
- ×OS-level DNS cache and HSTS pinning (browser-wide, profile-wide)
- ×Server-side state about you (account flags, audit logs, rate-limit counters)
The right column is the part competing guides skip. Most flaky "but it worked in incognito" bug reports trace back to one of those rows: an extension that was on, a fingerprint-based cohort that stuck, a server-side flag the user's account still carries, or a download that was not actually fresh. Read the column before you trust the test.
The four-step recipe
One discipline that catches most mistakes: do not skip the verify step. People open private mode, click around, see the right thing, and ship. The right thing is sometimes the cached thing the regular session remembered, served from the browser's shared HSTS list or DNS cache. Verify on the network panel before you call it done.
- 1
Open private
Cmd+Shift+N on Chrome, Edge, Brave, Arc. Cmd+Shift+P on Firefox and Safari. On Windows or Linux, swap Cmd for Ctrl. Verify the title bar or window chrome shows the private indicator.
- 2
Reproduce
Paste the URL of the feature you are testing. Walk the flow from the entry point a stranger would actually hit (homepage, share link, ad landing) rather than from a deep link an authenticated user would.
- 3
Verify
Check three things: the rendered UI for first-time hints (modals, banners, tooltips), the network panel for unexpected 401s or stale cookies, and the console for errors that only fire on a fresh storage state.
- 4
Discard
Close every private window from this session. State is gone the moment the last private window closes; do not assume one closed window resets the others.
Total wall-clock for one pass: about 90 seconds. The slowest part is reading the network panel for the request you actually care about. If you find yourself running the recipe more than three times in a session, save the URL plus the prereqs in a sticky note; you are testing the same flow repeatedly and a Playwright script will pay for itself within an hour.
The shortcuts, every browser
Worth committing to muscle memory if you are testing across browsers regularly. Two shortcut families cover everything: Chromium-derived browsers use Cmd/Ctrl+Shift+N, and Mozilla-derived plus Safari use Cmd/Ctrl+Shift+P. The notes are the small differences that sometimes matter.
Chrome
Cmd+Shift+N (mac) / Ctrl+Shift+N (Windows, Linux). Extensions disabled by default.
Edge
Cmd+Shift+N / Ctrl+Shift+N. InPrivate mode. Same Chromium engine as Chrome.
Firefox
Cmd+Shift+P / Ctrl+Shift+P. More aggressive first-party isolation than Chromium private.
Safari
Cmd+Shift+N (Safari 14+) or File > New Private Window. Shorter cache lifetimes than Chrome.
Brave
Cmd+Shift+N / Ctrl+Shift+N. Plus a Private Window with Tor option for IP isolation.
Arc
Cmd+Shift+N. Inherits Chromium incognito; Arc's Spaces are not equivalent.
Vivaldi
Cmd+Shift+N / Ctrl+Shift+N. Same private session model as Chromium.
Opera
Cmd+Shift+N / Ctrl+Shift+N. Built-in VPN can be toggled for IP testing inside private mode.
Two practical notes. Brave's Tor private window is not the same as a regular private window; it actually does change your IP path through the Tor network and is slow but useful for geo-tests. Firefox's Total Cookie Protection isolates first-party data per top-level site, which makes some cross-site flows behave differently in Firefox private mode than in Chrome incognito; if you see a discrepancy across browsers, that is usually the cause.
What happens when you open mk0r in a private window
As a worked example: mk0r persists a session identity by writing a UUID to localStorage under the key mk0r_session_key on first page load. The logic lives in src/app/(landing)/page.tsx around line 32, in a function called getSessionKey. Open the regular tab and the function reads the existing key. Open in incognito and the function gets null, generates a new UUID with crypto.randomUUID(), writes it back, and the rest of the page treats this browser as a brand-new visitor. A fresh sandbox is claimed via the prewarm endpoint, and a session_started event fires in PostHog with the new key.
Cold open of mk0r in a private window
Two seconds, no signup, no logout, no profile switch. The whole point is that the private window naturally produces the empty-storage state that page.tsx is designed to handle, so the first-time visitor branch of the code is exercised verbatim. If you are iterating on a generated app inside mk0r and you store anything in localStorage yourself (a user's draft, a tutorial-completion flag, a cached preview), open the published preview URL in private mode to verify what a stranger's first visit actually looks like, before you ship the share link.
The five pitfalls that make private-mode tests lie
Each one of these has caught me, and each one looks innocent until you remember it.
1. The extension you forgot you allowlisted
Most extensions are off in private windows by default. But once a user opens chrome://extensions and toggles "Allow in incognito" on a single extension (often an ad blocker, a password manager, or a privacy tool) it stays on for every future private window forever. If your test result depends on knowing whether an ad blocker is active, list the enabled-in-incognito extensions before each test session.
2. The second private window that joined the first session
Open private window A, sign up for an account, leave it open, open private window B to test the logged-out marketing page. B is not logged out; it shares the auth cookie with A. Close window A first if you want B's storage to start empty. The granularity is private session, not private tab.
3. BFCache replaying a stale page on back-button
The back-forward cache caches a fully-rendered snapshot of the page you came from, including its in-memory React state. Click back inside an incognito session and you can land on a stale view that does not match the network state. To force a fresh render in a test, use a hard reload (Cmd+Shift+R) after navigating back, or open the URL in a new private tab instead of clicking back.
4. Server-side state your account still carries
Private mode clears the client. It does not clear the server. If your test logs into the same account from a private window, the account still has the same flags, audit-log entries, rate-limit counters, and feature-gate cohort assignments it had before. To test as a true first-time user, you also need a brand-new account, an unauthenticated path, or a server-side reset. Otherwise you are testing "same user, fresh browser", not "new user".
5. Fingerprint-based metering and bot scoring
Anti-fraud and metered-paywall systems often key off a fingerprint (TLS, canvas, font list, audio context) plus your IP, not just your cookie. Private mode does not change any of those signals. The third paywall hit from the same browser still reads as the third hit; the bot-score still recognizes the device. To genuinely simulate "new device", you need a different machine, a fresh VM, a residential IP swap, or a tool like Multilogin or a Playwright stealth profile, not an incognito window.
Real scenarios where private mode is the right answer
The tool fits a specific shape of testing problem: you need to see a logged-out, no-storage state from your normal machine without losing your real browser session. That covers more day-to-day tasks than people credit it for.
The pattern across all of these: you need empty client storage and an unbiased first-visit path, but you do not care about IP isolation or fingerprint reset. If your test does care about those, escalate to a fresh profile, a fresh VM, or a residential proxy.
When to graduate from incognito to something stronger
Three escalation paths, in increasing order of overhead. None of them replace incognito for the day-to-day; they fill the holes incognito leaves.
First, a fresh browser profile. Open Chrome's profile menu, create a new profile pinned to the dock, and use that profile for testing. Heavier than incognito (you have to log in to extensions and dev tools again) but lets you see real browsing history, run extensions, and persist a stable cookie identity across sessions. Useful when you want to come back tomorrow and still be the same test user.
Second, a Playwright script with storageState set to an empty object on each run. Reproducible, scriptable, runnable in CI. The cost is about an hour of setup the first time, then it amortizes across every future test. mk0r uses this internally to verify generated apps before showing them back to the user; the same approach works for any web app you are iterating on.
Third, a fresh cloud VM with its own residential IP. Heaviest, slowest, but the only way to truly simulate a different device on a different network. Worth it when the feature you are testing depends on geo-routing, IP-based rate limiting, or any system that fingerprints the network rather than the browser. mk0r's own VM mode runs Chromium inside an E2B sandbox with an optional residential IP layer; the same primitive works as a one-off test rig.
Want help wiring up first-visit tests for the app you are building?
Book 20 minutes. Bring the URL of what you are testing; leave with a checklist of which signals incognito catches for it and which ones you need a stronger isolation lane for.
Frequently asked questions
Frequently asked questions
Why use an incognito tab to test a feature instead of just logging out?
Logging out clears the auth cookie, sometimes. It rarely clears localStorage, sessionStorage, IndexedDB, the in-memory state of any single-page app, the BFCache snapshot of the previous page, or your developer-tools history. An incognito window starts the whole browsing context fresh: empty cookie jar, empty Web Storage, empty cache for everything fetched in that session, and a separate process tree on most modern browsers. You are testing the app from inside the closest thing to a stranger's machine without leaving yours.
What does incognito actually clear, in plain language?
Cookies set during the session, anything the page wrote to localStorage and sessionStorage, the HTTP cache for documents and assets fetched in that window, autofilled passwords (you start with none and lose any you save), and the browsing history record. When you close every incognito window from the same private session, all of that is discarded. Nothing about the previous regular session is visible to the incognito window in the first place.
What does incognito NOT clear, that catches people testing features?
Five real holes worth memorizing. (1) Browser extensions are usually disabled in incognito by default but a user can flip them on per-extension and then forget; an enabled ad blocker will lie to you about your real signup conversion. (2) On Chrome, downloads, bookmarks, and the global address bar autocomplete still record entries. (3) ServiceWorkers in some browsers can persist cached responses across incognito sessions if registered before incognito was opened (uncommon, but real on long-lived profile-bound caches). (4) Your IP, fingerprint, and OS-level network state are unchanged, so geo-detection, bot-detection, and rate-limiting see the same machine. (5) BFCache, the back-forward cache, can still serve a cached page snapshot when you click back inside the same incognito session, which masks broken navigation.
Are an incognito window and a private window the same thing across browsers?
Functionally close, named differently. Chrome and Edge call it incognito. Firefox calls it Private Browsing. Safari calls it Private. Brave has a tougher private mode plus a Tor private window option. Arc inherits Chromium incognito. The keyboard shortcut differs: Cmd+Shift+N (Chrome, Edge, Brave, Arc), Cmd+Shift+P (Firefox, Safari). Behavior under the hood differs in small ways: Firefox isolates first-party data more aggressively in some configurations, Safari has shorter cache lifetimes, Brave forces a separate session per private window. The 90-percent answer is: storage and cookies are scoped to the private session and discarded on close.
When is incognito the wrong tool for feature testing?
Three cases. First, when you need to verify behavior with a specific browser extension installed and active; incognito disables most extensions by default. Second, when the feature involves cross-device or push notifications that require a persistent ServiceWorker registration; private mode kills the registration on close. Third, when you need to verify behavior under realistic cache pressure, where some assets are warm and some are cold; incognito makes everything cold, which is unrealistic for returning users. For those three, you want a fresh browser profile or a clean container, not incognito.
How does this relate to mk0r specifically?
mk0r persists a session identity by writing a UUID to localStorage under the key mk0r_session_key on first page load (logic at src/app/(landing)/page.tsx around line 32). Open mk0r.com in a regular tab and you keep your existing session, projects, and pre-warmed VM. Open it in an incognito window and there is no key in localStorage, so the page generates a new UUID, fires a session_started PostHog event, and pings /api/vm/prewarm to claim a fresh sandbox. The result: in roughly two seconds you are testing as a brand-new visitor with a brand-new sandbox, no logout step required. This is the cleanest way to verify the first-time visitor experience for any app you are iterating on inside mk0r, and it is also a good pattern to copy into your generated apps if they store state in localStorage too.
Can I test a logged-in flow if there is no signup, like on mk0r?
Yes, that is the easiest case. With no signup gating the product, an incognito window is fully indistinguishable from a stranger's first visit. You exercise the entire build flow end to end, including PostHog event capture, VM warmup latency, the streaming preview pipeline, and any onboarding nudges. Close the window when done and the session is gone. For products that do require auth, you log in inside the incognito window, do the test, and the session evaporates on close.
What about testing a feature that depends on a paywall or a A/B-tested cohort assignment?
Cohort assignment usually keys off a cookie or a localStorage flag. Incognito guarantees both are empty, so you get a freshly assigned cohort each time you open a new private window. That is great for testing the assignment logic but bad for testing a stable cohort across visits, which incognito cannot simulate. For paywalls keyed on a server-side rule plus a client cookie, incognito tests the unpaid path cleanly. For metered paywalls that count visits across sessions via fingerprinting, incognito does not lie about the IP or fingerprint, so the metering still works against you on the second open, which is realistic.
Does incognito hide my IP or location from the site I am testing?
No. Incognito only changes what is stored on your computer. The site sees the same IP, the same general location, the same TLS fingerprint, and the same OS-level user agent it would see in a regular tab. If you need to test geo-routing or rate-limit behavior from a different IP, you need a VPN, a proxy, or a residential IP service, not an incognito window. mk0r itself uses a residential IP layer to give the in-VM Chromium an upstream IP that looks residential to target sites; that has nothing to do with the user's incognito state in the parent browser.
Is there a faster shortcut than opening incognito for every test pass?
Three options, in order of overhead. (1) Reuse the same incognito window across iterations and only close it when you want a fresh state; private storage persists for the lifetime of the private session, not per-tab. (2) Use a separate browser profile pinned to the dock, opened cold each time. Profiles are heavier than incognito but easier to inspect with a real DevTools history. (3) Use Playwright with storageState set to an empty object; this scripts the same effect and gives you reproducible test runs. mk0r uses option three internally to verify generated apps before showing them to you.