Not on a page that isn't this one — the browser refuses, and I have the exact error. On a page served from this same domain it loads and converts normally, producing the same bytes as it does standing alone.
Short answer: two different answers, depending on who is doing the embedding. A page on another domain cannot frame it: the response carries frame-ancestors 'self', and Chrome blocked the attempt with a security error rather than loading it. A page served from heicjpg.dev itself can frame it, and the framed copy converted a 41,465-byte HEIC to 38,078 bytes with the same SHA-256 the converter produces when it is not in a frame.
What I measured today (15 October 2026, Chrome 155.0.8059.40): six real conversions — three inside a same-origin iframe, three on the ordinary page as a control — plus one cross-origin embedding attempt from a locally served page, and one test where the converter framed itself.
The answer to any embedding question starts in the response headers. Fetching the homepage returns a Content-Security-Policy header that ends with frame-ancestors 'self'. That single directive is the whole policy: it says the page may only be framed by a document on the same origin.
There is no X-Frame-Options header at all — I checked, and it is absent. So the older header is not what blocks anything here; the CSP directive is. For completeness, the same header also contains child-src 'self' blob:, which is what allows the page to run its decoder worker from a blob: URL.
I loaded a page on this site, inserted an iframe pointing at the converter, and waited for the decoder to arrive inside the frame. That took 804 ms. Then I converted the same HEIC three times inside the frame:
| Run | Conversion time | Output | Page's size line |
|---|---|---|---|
| 1 (first, cold) | 1,784 ms | 38,078 B | frame.jpg — 700×476 — 37 KB |
| 2 | 379 ms | 38,078 B | frame.jpg — 700×476 — 37 KB |
| 3 | 228 ms | 38,078 B | frame.jpg — 700×476 — 37 KB |
All three produced SHA-256 93859de257dc44a7…, which is the same hash this file has produced on every run I have published. The control run on the ordinary, unframed page — same file, same browser session — gave 1,226 ms, 291 ms and 197 ms and the identical 38,078 bytes.
I read the framed page's own view of itself. It knows it is not the top window — window.top === window.self came back false — and window.frameElement pointed back at the iframe holding it. Its own address was / while the page around it was /guides.
Everything a visitor needs was there and in the right place:
| Element | Inside the frame |
|---|---|
| Upload area position | 288 px from the top, 84 px from the left, 714 × 180 px |
| Quality options | High — 95%, Good — 85%, Smaller file — 75% |
| Decoder | loaded and callable |
| Document readable by the parent | yes (same origin) |
The upload area sits at the same 288 px from the top inside the frame as it does on the page on its own, so a frame tall enough to show it gives you the same first screen.
I also tried the converter framing itself: the outer page's upload area stayed at 288 px after the frame was added, the decoder was callable inside the new frame, and the page reported one frame. Nothing broke.
For the other half of the question I served a page from http://127.0.0.1 containing an iframe pointed at https://heicjpg.dev/. The browser did not load it. The console carried exactly one entry, and it was explicit:
Framing 'https://heicjpg.dev/' violates the following Content Security Policy directive: "frame-ancestors 'self'". The request has been blocked.
The frame object still existed in the parent's DOM and contentWindow was present, but reaching into contentDocument threw a SecurityError — the framed document was never there to be read. This is the browser enforcing the policy, not the page detecting anything or showing a message of its own.
So if you were hoping to drop this converter into your own site's page: that is not something the site permits, and not something you can work around from the outside. It is a deliberate restriction, and it is also a reasonable one — a page that handles your photos should not be embeddable where someone else could overlay it.
sandbox or allow attributes. I used a plain iframe in every test, so I have not measured whether any attribute combination changes the same-origin result.'self', which excludes subdomains, but I do not have one to test against.frame-ancestors too, but I did not measure them today.No. The browser will block it — that is what the frame-ancestors 'self' directive does, and I watched Chrome refuse with a security error. If you want a converter on your site, you need one you host yourself.
No. Three conversions inside a same-origin iframe produced the same 38,078 bytes and the same SHA-256 as three conversions on the unframed page in the same session.
Not in any way I could separate from noise. Inside the frame: 1,784 ms then 379 ms then 228 ms. On the plain page: 1,226 ms then 291 ms then 197 ms. Both settle into the same couple-hundred-millisecond range after the first conversion, and both are slow on the first one.
There just isn't one — I checked the response headers and it is absent. The framing rule is carried entirely by the CSP directive, which is the modern mechanism and the one Chrome enforced in my test.
No, and the reason is the same as everywhere else on this site: the decoding happens in your browser and the file is never uploaded. Whether the page is top-level or framed does not change where your photo goes. I measured that at the network layer in Does the photo ever leave your device?.
Open DevTools, go to Network, reload the converter, click the first request and read the content-security-policy response header. The last directive in it is frame-ancestors 'self'.
That difference — same origin works, everything else is refused — is the whole answer.
Your photos are decoded in your own browser — open the converter and see.
First published: 15 October 2026