Your HTML-to-PDF file came out blank
You pointed a converter at a page, it thought about it for a second, and handed back a PDF with nothing on it. One page, white, maybe a header and a footer with a date in them.
The page itself is fine. It is open in the next tab. You can read it, select it, scroll it. Nothing errored, nothing warned, the job reported success, and the file is 4 KB.
So you tried a different converter and got the same nothing. That is the useful clue: three tools agreeing means they all received the same thing, and what they received was not the page you were looking at.
First, work out which blank you have
There are two, they look identical, and the fixes have nothing in common.
Open the PDF and try to select the text. Drag across the middle of the empty page, or press Ctrl+A.
- Nothing highlights. The file genuinely has no text in it, so the content never reached the converter. That is the next two sections.
- Something highlights — an invisible block of words, and copying gives you the article. The content arrived and was drawn where you cannot see it. Skip to the invisible kind.
If the page is too empty to drag across confidently, open the output in our PDF inspector. It runs in your browser, uploads nothing, and reports how many characters each page draws. Zero characters is the first kind. Four thousand characters on a page that looks white is the second, and knowing which saves you an afternoon of debugging the wrong half of the pipeline.
The empty kind: what arrived was the shell, not the page
A request for a web page returns one file: the markup the server had ready. What you see in your browser is what that markup looked like after the browser ran the scripts in it, fetched what they asked for, and built the content out of the results.
For a great many sites those two things now bear no resemblance to each other. The server sends a
skeleton — a <head> full of script tags, a <body> containing <div id="root"></div> and nothing
else — and everything you read is assembled afterwards, in your browser. React, Vue, Angular, admin
panels, dashboards, most single-page applications, and plenty of sites that look like ordinary
documents.
Hand that skeleton to something with no script engine and an empty document is the correct output, because there is nothing in the file. It is also why every converter gave you the same result: they are not failing at the same thing, they are all faithfully converting a page with no words in it.
The test that settles it in ten seconds. Press Ctrl+U (Cmd+Option+U on a Mac). That is View Source, the file the server sent — and it is not the Elements panel in developer tools, which shows the live DOM after every script has finished. Confusing those two is the whole misunderstanding, and it is why people are certain the content is obviously there. Search the source view for a sentence you can see on the page. From a terminal, the same test:
curl -s https://example.com/page | grep -c "a sentence from the page"
A zero means no script-free converter will ever find that text, and there is no setting to look for.
If you are driving a headless browser, the script engine exists and your problem is timing instead:
you printed before the page had built itself. waitUntil: 'load' fires when the document's own
resources are done, which on a client-rendered app is the moment before any content exists. Wait for
a selector that only appears once the data has landed, or give bare headless Chrome
--virtual-time-budget=10000.
The same symptom from the other direction: you got the login screen
The other reliable way to get a blank is that the converter never saw your page, because it is not you.
A server-side fetch carries no cookies, no session and no browser profile; it arrives as an
anonymous stranger and is given whatever a stranger gets. A redirect to /login, a paywall teaser,
a consent interstitial, a bot check. Most converters follow the redirect and convert what they find,
so you get a one-page PDF reading "Sign in to continue" — or a blank one, because sign-in screens
and bot checks are themselves script-built.
Our HTML to PDF will not fetch a page that answers with anything other than 200, and tells you the number, so a silent blank becomes "that page answered with status 403". If markup does come back but holds no text at all, it refuses that too, with the reason, rather than handing you an empty PDF to puzzle over later.
The fix for both: save the page, then convert the file
Both causes are the converter seeing something different from what you saw. So stop sending it an address and send it exactly what is on your screen.
On the fully loaded page, press Ctrl+S (Cmd+S). This is not a fresh download. The browser serialises the DOM it currently holds — after the scripts have run, after you logged in, after everything loaded — and writes it to disk as HTML. Content that exists only because JavaScript built it is baked in as ordinary markup, and so is content that exists only because you have a session.
- Load the page properly. Log in, dismiss the cookie banner, and scroll to the bottom so anything lazy-loaded has actually loaded.
- Ctrl+S. "Webpage, Complete" saves the markup plus a folder of assets; "Webpage, HTML Only" saves a single file. For a text conversion either will do, because only the markup is read.
- Search the saved file for a sentence from the article in any text editor. Thirty seconds, and it confirms the words are in there before you convert anything.
- Convert the file instead of the address. Upload it to HTML to PDF, pick A4 or Letter, a margin, a text size and one of four typefaces, and read the result as a document rather than a picture of a web page.
For a page that builds itself in the browser this is not a workaround bolted onto a broken tool. It is the correct procedure whatever converter you use.
The invisible kind: a print stylesheet hid the page
Now the other blank, where the text is in the file and you cannot see it. This one only happens with converters that have a real browser behind them, and the reason is worth knowing.
A headless browser makes a PDF through the print path, so it renders the page under
@media print, not @media screen. Print stylesheets exist to strip a page down for paper, and
they are usually written once, tested on one template, and never looked at again. The usual ways
one blanks a page:
display: noneon the wrong container, where a rule meant to drop the navigation matches a wrapper holding the article too.- The "print only this div" recipe.
body * { visibility: hidden }followed by#invoice, #invoice * { visibility: visible }has been copied out of Stack Overflow into thousands of sites. If your content is not inside that one id, everything is hidden and nothing is put back. - A container with
height: 0oroverflow: hidden. On screen it scrolls; on paper the overflow is simply not drawn. position: fixedcontent, which is painted on the first page only, or on none.- White text with the background switched off. Backgrounds are not printed by default, so pale text on a dark hero becomes pale text on white paper: present, selectable, invisible. That is the same default that drops the images out of a conversion, showing up as a different symptom.
You can watch it happen. In Chrome DevTools open the command menu (Ctrl+Shift+P), run "Show
Rendering", and set "Emulate CSS media type" to print. The page goes blank in front of you with
the responsible rule sitting in the Styles panel. In Puppeteer, page.emulateMediaType('screen')
skips the print stylesheet altogether and printBackground: true handles the white-on-white case.
If the source was never a live page
Sometimes the address was not the point. If what you want as a PDF is a README.md, a changelog, a
.txt export or a saved HTML email, Word to PDF takes those directly and sets
them as a typeset document — and it is worth knowing
what falls off a Markdown file on the way before you send the result
anywhere. It refuses .docx, deliberately, with an explanation.
If two charts off an unconvertible page are all you need, take the picture route. Chrome's command menu has "Capture full size screenshot", which grabs the whole scrolling page rather than the window; save as PNG and JPG to PDF turns the images into pages. It reads a photo's EXIF orientation too, so a snap taken sideways on a phone comes out the right way up.
When something else is the right tool
If you need the PDF to look like the page, use something with a real rendering engine. All three are free.
- Print the page from the browser you are reading it in. The print dialog's Save as PDF has the whole engine behind it, along with your session, your cookies and the DOM as it was actually built. For one page, once, nothing beats it — and if that comes out blank you have proved the problem is the print stylesheet, which is the section above.
chromium --headless=new --virtual-time-budget=10000 --print-to-pdf=out.pdf https://example.comis the same engine from a command line. Drive it through Puppeteer when you need a wait condition,emulateMediaType('screen'),printBackground: trueor a logged-in session.- SingleFile is a browser extension that saves the rendered page as one self-contained HTML file with the styles and images inlined. It is the automated version of Ctrl+S and the tidiest way to get a script-built or logged-in page into a file you can convert or keep.
Whichever you use, keep the select-all test. A blank page and a page of invisible text are two different faults wearing the same white sheet, and telling them apart takes two seconds.