Security & how to verify it
Your PDF is processed locally, in your browser. Our converter code does not upload it. A separate website and a restrictive security policy limit what the converter can do on the network. This page explains exactly what that means, what it doesn't mean, and how to check it yourself.
1. The airplane-mode test (anyone can do this)
- Open any page on this site and wait for it to load.
- Turn on airplane mode, or disconnect from Wi-Fi.
- Drop your PDF into the box. It opens anyway.
This shows the conversion itself doesn't need a server. It's a quick check, not a proof. The technical checks below go further.
2. How it's built
- A separate website for the converter. The converter runs on
convert.cantopenpdf.com, isolated from this site by your browser's same-origin rules. Scripts on this site, including our analytics, can't read your file. That host serves static files only and has no server code. - No third-party hosted or tracking scripts. No ad networks, no Google Analytics, no CDNs. Every script is served from our own domains. The PDF engine, Mozilla's pdf.js 6.4.299, is third-party open-source code that we host ourselves, unmodified and pinned to an exact version.
- Read-only pages. Embedded PDF scripts never run, document links aren't followed, and form fields and buttons are disabled.
- No cookies or device storage. Neither site sets cookies or uses local storage, session storage or IndexedDB.
3. What the security policy does, and doesn't do
The converter's Content-Security-Policy includes default-src 'none', connect-src 'self', form-action 'none' and frame-src 'none'. Your browser enforces it. It:
- blocks the page from making network connections (fetch, XHR, WebSocket) to any host other than the converter's own static host
- blocks form submissions and loading scripts, frames or plugins from anywhere else
It doesn't, on its own, prove that no data could ever leave your device:
- Requests to the converter's own host are still allowed, for example to load fonts.
- It doesn't govern messages the converter sends to this site (see section 4) or links you choose to follow.
- It can't protect against browser extensions or malware already on your device.
Our guarantee is that our code doesn't send your document anywhere. The policy is an extra layer that limits the damage if something went wrong.
4. Exactly what the converter tells this site
The converter sends this page short messages so we can show relevant help and count what works. Each message can contain only:
- an event name (file opened, displayed, failed, incomplete, password needed, print requested)
- a document type from a fixed list built into the code, for example
sars:audit,ircc:imm5257,unknown - the number of pages, a size range (such as “0.5–2 MB”), and whether the file was an XFA form
The converter never sends text, names, numbers, reference codes or field values from your document, and anything outside the fixed list is reported only as unknown. This site checks every message against the same list before recording it. See post() in app.js and the list in catalog.js.
This site records those events, plus the page you're on and how you arrived (campaign tags, referring site, country and device type), with a random visit ID that lives only in the page and in the link to our help form. It isn't stored on your device and isn't reused on later visits. Details are in the privacy notice.
5. Check it yourself (technical)
- See the policy:
curl -sI https://convert.cantopenpdf.com/ | grep -i content-security-policy - Open your browser's developer tools, go to the Network tab, and convert a file. The only requests go to
convert.cantopenpdf.comfor the app's own static files. - Our code isn't minified. Read app.js, detect.js and catalog.js directly.
- Compare pdf.js with the official package:
npm pack [email protected], thenshasum -a 256 package/build/pdf.min.mjs(served here aspdfjs-6.4.299/pdf.min.mjs).
The hashes below are published by the same server they describe, so they're useful for comparing files, not independent proof of where the files came from. Our CI checks selected invariants on every change: the security policy directives, a list of files allowed in a release, byte-identical pdf.js, and a browser test that a document's text never appears in any network request or message.
Converter file hashes (SHA-256)
Release 09d94111cf6f, built 2026-11-04T13:48:10.043Z. Fonts, character maps and colour profiles are listed in SHA256SUMS.txt.
| File | SHA-256 |
|---|---|
_headers | 16e056bcd8fe126b6c856a3300c9031e84e535855072130af8c2d51689b6b2cf |
app.js | af229b45184c1f679f20247063fbfb48aba637b14aa096b293fe0e018acc4ba4 |
config.js | b3250cb7d51b7fadd5d6f2bacadb375a07f76e61e6ea778dbaa8d83d74a71770 |
convert.css | 11b82b902229cbeb66495349d008f99eac9b71ab41824d8993865889392d3820 |
detect.js | 315a409272357faf4afffbf0890435c24c47c0cbe3414ad099b8efdda6185143 |
favicon.svg | ac6e9d6a2c011a002d43f9c59620f18183ee92c7501c97bae7fcf2ef998f6729 |
index.html | b67f00d00308e7e2439f0f35ec89e6d6ea5e5f279485bc0a8b00f7140ac9c090 |
js-normalize.js | 9cf981fb884065013123694622e7adb3e46f724200c2af3f45ed15d1555c88aa |
pdf-xfa-worker.js | 2e4e0b9f4165c05b941825d933ac4dc11312270e389b8cf6247b53bf7d2c63ae |
pdf-xfa.js | 793d980da24f567765ab3b4714b85a1e47a2e325d4e08b8cb047e504feae1d9f |
pdf417-tables.js | 04e6be0b0ffebe03ee52615c7a4cd7be7e5e00601de4b17049a7a3e1a63da8b1 |
pdf417.js | 67aa53d01ec3c74307d366b2c5886ef0731cb5ae21119b74b0b52cf446e72cfa |
pdfjs-6.4.299/LICENSE | 0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594 |
pdfjs-6.4.299/pdf.min.mjs | 57456c8e0c81e46be31174b499ef77f2b9f5ee46d04412ba627320a36755d4c2 |
pdfjs-6.4.299/pdf.worker.min.mjs | 9536359f1b8367850d485731ca1d5e45c159a7b7a0912325e539937aa21ceb18 |
pdfjs-6.4.299/wasm/LICENSE_JBIG2 | 9e66b7f1b934a28b37f3bc4dac97915de1674271e79a0a88182a18ed9731b4d1 |
pdfjs-6.4.299/wasm/LICENSE_OPENJPEG | a6af136f3e15038a666b61f376612a07d9a4e48cb7c01adbf3e33b3f14ab49b6 |
pdfjs-6.4.299/wasm/LICENSE_PDFJS_JBIG2 | aad3cce09842e00e9e11ad5e8fef8cc02fbc3a3768fe2f007443b9cee37aaee5 |
pdfjs-6.4.299/wasm/LICENSE_PDFJS_OPENJPEG | 717fc62da03292dbb4dd0c8280bd4ce7bb8550dcf31d772bc93455fb50313425 |
pdfjs-6.4.299/wasm/LICENSE_PDFJS_QCMS | 508a77d2e7b51d98adeed32648ad124b7b30241a8e70b2e72c99f92d8e5874d1 |
pdfjs-6.4.299/wasm/LICENSE_QCMS | 36d847ae882f6574ebc72f56a4f354e4f104fde4a584373496482e97d52d31bc |
pdfjs-6.4.299/wasm/jbig2_nowasm_fallback.js | 68686ced624a48c42f84cdaa482ec44b72b0de4dc84a0df903af1fb7b45b5d9a |
pdfjs-6.4.299/wasm/openjpeg_nowasm_fallback.js | 9047b34b6bc142d85e4b0aa1b08b0b9baad4c6f8b7ac87641b9e8f90eb6fd23e |
release.json | 7de1a061c25d1bc897a4ec33431f017abddad168ef24c23f6a30daecbd067413 |
robots.txt | 331ea9090db0c9f6f597bd9840fd5b171830f6e0b3ba1cb24dfa91f0c95aedc1 |
shared/catalog.js | 8f625849ea6c41cd7f853649dadd4474a860cd5de2b12fec37734ea067b3e890 |
xfa-fixups.js | d463b7aa929df05cbdc6f740f93cbfbb91ea2dff0913be3eca4f9cbf92e60937 |
xfa-prepare.js | df89982bfb94617901cd6191d4ad39223f8f3257f4f99b1ada60546a0abf0789 |
xfa-scripts.js | d61783e78f502bc0fe29c2050b5abf186c037685568033635560128178c87248 |
xfa.css | c343704d5d804a2ccc57e65cf323ded52c0b1bcd8523089f468be964ce1c7c19 |
Report a problem
Found a security issue? Email [email protected]. See also security.txt.