PDF Handouts

Merge PDFs and screenshots into one printable handout, with a title, footers and page numbers.

Your files never leave this page. Everything runs inside your browser β€” nothing is uploaded to a server. Don't take our word for it β†’

1 Choose your files

Drop files here

or click to browse β€” PDF, PNG, JPEG, GIF, WebP

2 Set the page furniture

Centred at the top of the first page.

today, 2026-07-28, Tuesday or Tuesday+1. Fills the [date] placeholder.

Use | for a line break, and the placeholders [page], [pages], [date]. Wrap text in [font italic]…[/font] or [font bold]…[/font] for inline styling.

Advanced

e.g. 24pt bold #1a4d8f

Keeps source pages clear of the title and footer.

3 Build it

Loading…

Checking the claim yourself

A web page cannot prove its own innocence. Any reassuring badge it shows you would look exactly the same on a page that was uploading your files. So rather than ask you to trust a claim, here are four ways to check it β€” none of which rely on anything this page tells you.

  1. Pull the plug

    Once this page has loaded, disconnect from the internet β€” turn off wi-fi, or use your browser's offline mode. Now add your files and build. It still works. Nothing that needs a server could do that.

  2. Watch the network

    Open your browser's developer tools, go to the Network tab, clear it, then build a handout. There are no requests. The only traffic this page ever makes is fetching itself when it first loads.

  3. Make it try to leak, and watch it fail

    This page ships a Content Security Policy that the browser enforces β€” the page cannot switch it off or work around it. You can read it near the top of the page source. To see it working, paste this into the developer console and watch every attempt get refused:

    fetch('https://example.com/x', {method:'POST', body:'test'});
    new WebSocket('wss://example.com/x');
    navigator.sendBeacon('https://example.com/x', 'test');
    new Image().src = 'https://example.com/x?d=test';

    Browsers make you type allow pasting in the console once before they let you paste anything β€” a sensible precaution you should keep. Nothing above sends real data; it only tries to reach a dummy address so you can see the refusal.

  4. Read it, or build it yourself

    The whole thing is open source. The page is a few hundred lines of plain JavaScript with no dependencies and no build step, so what you see in the source is exactly what runs. The PDF engine is Rust compiled to WebAssembly, and you can compile it yourself from the same source and compare it against what is served here.

    Source on GitHub β€” the same tool is also a command-line program, if you would rather not use a browser at all.

One honest caveat: the policy permits requests back to the origin this page came from, because that is how the WebAssembly module itself is loaded. That origin is GitHub Pages, which serves static files and has nothing on the other end that could receive an upload β€” but if that is not good enough for your documents, use the command-line version, which has no network code at all.