Yes, it works, and the file you get out is the same file. I ran 20 conversions today across two ordinary Chrome sessions and two private ones: every small photo came back as the same 38,078-byte JPG and every 12-megapixel one as the same 3,177,680-byte JPG, byte for byte. What a private window changes is Chrome's own bookkeeping, not the converter — it re-downloads the decoder every single session, hands the analytics cookie a brand-new client id each time, and writes nothing into your history. What it does not change is the part people assume it does: the JPG you download is an ordinary file on your disk and it is still there after you close the window.
Short answer: a private window converts HEIC to JPG exactly as a normal one does, and the output is not affected in any way I could detect. All 16 conversions of the same 700 × 476 photo produced a 38,078-byte file with one SHA-256 hash, and all four conversions of the same 12-megapixel photo produced a 3,177,680-byte file with another — across both window types, across separate browser sessions, and across separate private sessions.
What a private window does change is the state Chrome keeps. It will not use the decoder it already cached, so it downloads it again from scratch: 690,159 bytes from heicjpg.dev in a private session against 5,759 in a warm normal window — about 120 times as much, for a page that is otherwise identical. The analytics cookie gets a fresh client id in every private session. And the profile's history database gained nothing at all across both private sessions, while each normal session added to it.
What it does not change is the one thing people usually assume: the downloaded JPG is not ephemeral. All four downloads landed on disk at 38,078 bytes with the same hash as the copy in memory, and all four were still there after I closed the browser. A private window forgets that you visited; it does not take the file back.
How I measured it: today, in Chrome 154.0.8037.99 on Windows, against the live page, driving a real browser over the DevTools protocol. Four sessions: two normal, two private, each loading the real site, converting four photos and downloading one. The live page's HTML today is 14,470 bytes, with one file input, one quality menu, and the upload box 288 px from the top of the window — the same in all four sessions.
I want to be precise about this, because it is the one place where my setup is not what you would do by hand. I first tried Chrome's own --incognito switch, and it did nothing: a window launched with it still read the localStorage, IndexedDB, cookies and disk cache of the ordinary profile, in headless and in normal windowed mode alike. I verified that twice, so it is not a one-off.
What I used instead is the browser context that Chrome's DevTools protocol creates on request — an off-the-record context, which the protocol documentation describes as being similar to an incognito profile. I confirmed it really is isolated before I trusted it, in four independent ways: it saw none of the storage the normal profile had written, it received a brand-new analytics cookie, it re-downloaded the decoder even though the ordinary window in the very same browser had it in cache, and it added nothing to the history database. Everything below is measured inside such a context.
The honest limit: I did not test a literal Ctrl+Shift+N window, because the switch that would create one is inert on this build. I also only have Chrome here, so nothing below says anything about Safari's or Firefox's private windows.
Each session converted the same 700 × 476 photo (41,465 bytes) three times plus once in a second tab, and the same 12-megapixel photo (11,084,868 bytes, 4,032 × 3,024) once. Every result is here:
| Session | 700 × 476 photo | 12-megapixel photo | Second tab |
|---|---|---|---|
| Normal, brand-new profile | 1,043 / 309 / 152 ms → 38,078 B | 7,691 ms → 3,177,680 B | 1,599 ms → 38,078 B |
| Normal, same profile again | 975 / 155 / 205 ms → 38,078 B | 5,033 ms → 3,177,680 B | 791 ms → 38,078 B |
| Private session 1 | 1,392 / 322 / 149 ms → 38,078 B | 5,340 ms → 3,177,680 B | 693 ms → 38,078 B |
| Private session 2 | 1,274 / 335 / 176 ms → 38,078 B | 5,222 ms → 3,177,680 B | 743 ms → 38,078 B |
That is 20 conversions producing exactly two distinct files. The 38,078-byte one hashes to 93859de257dc44a7ff3dc41eb965d07ff84c8630ec8a3db44e24e89120713c81 every time; the 3,177,680-byte one to 56ee525f012aa19f42998a4edc7a23a3d37f1fae975b649e4e6ba990b667b003. Those two hashes are the same ones I have been getting out of this page for days, so the private window did not even introduce a new variant — it reproduced the ordinary one.
Timings carry no signal about the window type. The fastest and the slowest small-photo conversion in the whole set were 149 ms and 1,599 ms, and both extremes appear inside both kinds of session; the first conversion of a session is always the slow one because the decoder has just arrived. The 12-megapixel runs landed between 5,033 and 7,691 ms with no ordering by window type.
This is the only real cost of using a private window here, and it is not small. The decoder script is by far the largest thing the page fetches, and a private window refuses to reuse the copy Chrome already has:
| Session | Requests | Bytes from heicjpg.dev | Decoder | Usable after |
|---|---|---|---|---|
| Normal, brand-new profile | 7 | 692,416 | 680,047 from network | 1,040 ms |
| Normal, same profile again | 5 | 5,759 | 0 — from cache | 1,166 ms |
| Private session 1 | 5 | 690,159 | 680,023 from network | 622 ms |
| Normal tab in that same browser, same minute | — | 6,158 | 0 — from cache | 1,174 ms |
| Private session 2 | 6 | 690,603 | 679,992 from network | 836 ms |
The fourth row is the one that makes the point cleanly, because it is not a comparison between two different browser sessions: inside one running browser, at the same moment, an ordinary window got the decoder for 0 bytes out of cache while the private context in that very browser paid 680,023 bytes for the same file. Private contexts do not share the ordinary cache, and they do not keep one of their own after they close.
What private does share is its own session. In each private session I opened a second tab, and the decoder arrived there for 0 bytes — the context caches what it fetched for as long as the context lives. So the cost is per private session, not per private tab.
One thing I expected to find and did not: the page did not become usable noticeably later. The times range from 622 to 1,166 ms and they do not sort by window type — the fastest of all five was a private session. I am not going to claim a speed penalty; on this machine and this connection, fetching it again did not move the needle enough for me to measure.
The site sets analytics cookies through the Google tag on the page. In the ordinary window, the identifier persisted: the client id was 2059012982 on the first visit and 2059012982 again on the second, several minutes and a full browser restart later. The private sessions minted a new one each time — 1270732602 in the first, 229181101 in the second. Same page, same scripts, three different identities.
History behaved the way private browsing is supposed to. I counted how many times the site appeared in the profile's history database after each session: the first normal session left 6 mentions, the second took it to 8, and both private sessions left it at 8 — unchanged. Whatever Chrome records about a normal visit, it recorded nothing for the private ones.
The converter itself stores nothing in either mode. Before I wrote anything of my own, the page's origin had 0 localStorage keys in all four sessions, an empty IndexedDB in three of them, and an empty Cache Storage in three of them. The one exception is the second normal session, where IndexedDB and Cache Storage each held exactly one entry — the probe I had written myself in the first normal session. Nothing the site wrote came back, because the site writes nothing. A private window's storage isolation is real, but on this page there is nothing of the site's for it to isolate; see the network-layer measurement for the other half of that picture.
It does not take the JPG back. I downloaded one file per session and let the browser close completely. All four were still on disk afterwards: N1_dl.jpg, N2_dl.jpg, P1_dl.jpg and P2_dl.jpg, each 38,078 bytes, each hashing to exactly the value the page had in memory when I clicked. A private window discards the record of your visit, not the file you saved. If the reason you opened one was that you did not want the converted photo left behind, it did not do that.
It does not block the third-party scripts. All three cold sessions — both private ones and the first normal one — fetched 191,130 bytes from two third-party hosts, www.googletagmanager.com and static.cloudflareinsights.com. The warm normal reload fetched 0, but only because they were cached. Blocking those is a separate job; the measurement with analytics blocked shows the converter works fine either way.
It does not change the storage you are allowed. The page reported a storage quota of 10,737,492,127 bytes in the private contexts and 10,737,420,433 in the ordinary window. Those two numbers are the same for any practical purpose, so I am not going to dress the difference up as a finding.
It does not change what happens if you close the tab mid-conversion. That is already covered in the interrupted-conversion measurement: the work is lost either way, and the one thing that survives is a download you already clicked.
If you want the conversion to work, it makes no difference — use whichever window you have open. If you care about the traces, a private window does two useful things on this page: the identifier in the analytics cookie does not follow you from session to session, and the visit does not appear in your history. It does nothing about the third-party scripts, and it does nothing about the file you save, which is the part most likely to outlive the session.
The one real cost is bandwidth: roughly 690,000 bytes per private session instead of roughly 6,000, because the decoder — the thing that does all the work, described in more detail in what the decoder is — has to be fetched again each time. On a phone on a metered connection, opening a private window for a single photo is the expensive way to do it.
Yes. All 10 conversions I ran inside private contexts succeeded, and every one produced a file byte-identical to the same conversion in an ordinary window — 38,078 bytes for the small photo, 3,177,680 for the 12-megapixel one.
No. Same size, same SHA-256 hash, same 700 × 476 or 4,032 × 3,024 dimensions. The output is deterministic regardless of window type, which matches what the byte-identical conversion measurement found.
Because it will not read the decoder Chrome cached for your ordinary windows, and it does not keep a cache of its own once it closes. I measured 690,159 bytes from heicjpg.dev in a private session against 5,759 in a warm ordinary one.
No. All four downloads in this test were still on disk, complete and unmodified, after the browser had been closed. Private browsing clears browsing state, not files you saved.
No. Both private sessions loaded 191,130 bytes from two third-party hosts, exactly as the cold normal session did.
Nothing I could find in either mode: 0 localStorage keys, empty IndexedDB and empty Cache Storage before I wrote anything myself. The cookies on the page come from the analytics tag, and in a private window they are recreated from scratch every session.
Three things, stated plainly. I did not test a real Ctrl+Shift+N window, because --incognito has no effect on this Chrome build; everything here comes from an off-the-record browser context, which I verified is isolated but which is not the same click path you would use. I did not test any browser other than Chrome, so Safari and Firefox private windows are unmeasured here. And I could not get a consistent answer on whether my own localStorage probe survives an ordinary restart — it came back in one of three runs and not in the other two — so I make no claim about localStorage persistence in either direction.
Try it: open a private window and convert a photo, then look for the file in your downloads folder afterwards. It will be there.
First published: 10 October 2026