Hardware FixRecommendedDevice not working? Your driver may be the problemCheck updates for common hardware issues.Fix DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsClean PCRecommendedOne scan can reveal what keeps slowing WindowsLook for cleanup and repair opportunities.Run Scan×
Skip to content
World desk7 min

Convert HTML to PDF in Go with Headless Chrome

Use chromedp and Chrome’s Page.printToPDF method to turn a rendered page into a PDF from Go, with a CLI alternative and practical layout and troubleshooting guidance.
Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Use chromedp to control Chrome from Go, wait for the page to be ready, and call Chrome DevTools Protocol’s Page.printToPDF method. It returns PDF bytes that your program can write to a file. For a simple URL-to-file job, Chrome’s headless command line can print a page without a Go browser workflow.

Choose the Go workflow or Chrome’s command line

Both approaches use Chrome’s print pipeline; the useful difference is how much control your program needs.

As an Amazon Associate I earn from qualifying purchases.

Approach Best fit Control and configuration Lifecycle
Chrome CLI A shell job that prints a URL directly to a file. Command-line flags set capture timing and suppress the built-in header and footer. Your process invokes Chrome as an external command.
Go with chromedp A Go application that must navigate, interact with the page, or coordinate browser actions. Go calls the CDP print method and can set its paper, margin, orientation, header/footer, page-range, and other options. Go manages browser and tab state through chromedp contexts.

This is a comparison of the documented interfaces, not a performance benchmark. Chrome’s CLI documentation says that --print-to-pdf saves the target page as output.pdf in the current working directory. Chrome Headless command-line reference

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Install Go dependencies and provide Chrome

Install chromedp and its generated CDP bindings with Go tooling, and ensure a compatible Chrome or Chromium executable is available in the environment where the program runs. Pin dependency versions in your project rather than relying on whatever version happens to be latest: generated binding signatures can change. Consult the chromedp repository for installation guidance and its headless-shell option for headless deployments; check the matching cdproto page binding for the version you pin.

Convert a URL to PDF with Go

The example below navigates to a URL, waits for the document body to be ready, prints with background graphics and CSS page sizing enabled, then writes the returned bytes. It expects Chrome to be installed and discoverable by chromedp. Replace the example URL with your own; for generated HTML, serve it locally or navigate to an appropriate file URL.

package main

import (
	"context"
	"log"
	"os"
	"time"

	"github.com/chromedp/chromedp"
	"github.com/chromedp/cdproto/page"
)

func main() {
	ctx, cancel := chromedp.NewContext(context.Background())
	defer cancel()

	ctx, cancel = context.WithTimeout(ctx, 60*time.Second)
	defer cancel()

	var pdf []byte
	err := chromedp.Run(ctx,
		chromedp.Navigate("https://example.com"),
		chromedp.WaitReady("body", chromedp.ByQuery),
		chromedp.ActionFunc(func(ctx context.Context) error {
			var err error
			pdf, _, err = page.PrintToPDF().
				WithPrintBackground(true).
				WithPreferCSSPageSize(true).
				Do(ctx)
			return err
		}),
	)
	if err != nil {
		log.Fatalf("navigate or print page: %v", err)
	}

	if err := os.WriteFile("output.pdf", pdf, 0644); err != nil {
		log.Fatalf("write PDF: %v", err)
	}
}

The print call’s generated Go signature can vary with the pinned binding version; confirm its return values and builder methods in that version’s page.go. The CDP method is Page.printToPDF, documented as printing a page as PDF. Chrome DevTools Protocol Page domain

Load generated HTML instead of a remote page

If your Go program generates the markup, write it to a temporary HTML file and navigate Chrome to its file URL, or serve it from a local HTTP endpoint and navigate to that endpoint. A local server is often preferable when the page expects relative assets, application routes, or browser-origin behavior. Ensure referenced stylesheets, fonts, images, and scripts are reachable before printing.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Wait for the page your application actually needs

WaitReady("body", ...) checks that the body is ready; it does not prove that a single-page application has finished rendering, that remote fonts loaded, or that images and asynchronous data have arrived. Wait for an application-specific selector or state when available, for example a report container your page renders only after its data is ready. A generic sleep is not a reliable readiness test. Chrome’s CLI offers timing controls, but those do not establish a universal readiness condition for every page.

Set print layout and PDF options

Use print CSS to design the document and CDP parameters to control the print job. Page.printToPDF supports portrait or landscape orientation, paper dimensions, margins, scale, page ranges, header and footer templates, background printing, and related settings. Its protocol reference also documents CSS page-size preference, tagged PDF generation, document outlines, and stream transfer mode. Check the protocol and the matching Go binding for the exact field names and availability in your pinned versions.

  • Paper and orientation: Set paper dimensions or choose landscape when the content is wider than it is tall.
  • Margins and scale: Tune these when content clips or when you need a predictable printable area.
  • Headers and footers: Configure templates when you want page metadata; the generated binding defaults to not displaying them.
  • Backgrounds: The generated binding defaults to not printing background graphics; enable them if the design relies on colored blocks or background images.
  • CSS page sizing: Use @page and @media print for document-authored print layout. With CSS page sizing not preferred, the protocol says content is scaled to fit the paper size; enabling preference lets CSS page size inform the output.
  • Page ranges: Request selected pages when you do not need the entire document; validate the syntax against the protocol binding version you use.

The protocol binding defaults include portrait orientation, no displayed header or footer, no print backgrounds, and PreferCSSPageSize set to false. Explicitly set the options your output requires rather than assuming screen styles automatically match print output.

Print a URL with Chrome’s headless CLI

For a one-off conversion or shell workflow, run Chrome directly:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
chrome --headless --print-to-pdf https://developer.chrome.com/

Chrome writes output.pdf in the current working directory. To suppress the date/time header and URL/page-number footer, add --no-pdf-header-footer. The CLI also supports --timeout, which sets a maximum wait before capture even if loading is ongoing, and --virtual-time-budget, which fast-forwards time-dependent page code for capture. These flags control timing; they are not proof that a particular app has completed all asynchronous work. Chrome documents that older versions may require --print-to-pdf-no-header instead of --no-pdf-header-footer. Chrome Headless command-line reference

Or skip the browser setup

If you need a one-call page capture rather than a Go-managed print workflow, ScreenshotNeo is a website screenshot API and MCP server. Its documented GET endpoint accepts a URL and can return an image or PDF. Example request:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo API documentation for request options and PDF configuration. ScreenshotNeo accepts cookie and consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; these steps can be turned off. Bot checks/CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify the page verdict and billing status in headers. An MCP server exposes take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots.

Sign up free for 1,000 screenshots a month, with no card required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshoot common conversion problems

  • Chrome cannot be launched: Confirm a compatible Chrome/Chromium executable is installed and available to chromedp in the runtime environment. In container deployments, use the project’s documented headless-shell option if appropriate.
  • Navigation or printing times out: Check that the target is reachable from the machine running Chrome and that its resources are not stalled. Increase the operation deadline only when the workload needs it; use a page-specific readiness condition rather than assuming a longer wait solves incomplete rendering.
  • The PDF is blank or missing content: Verify the page actually rendered in that environment and wait for the relevant application state, fonts, images, or data before printing. A body-ready check alone may be insufficient.
  • Colors or backgrounds are absent: Enable print backgrounds with WithPrintBackground(true) and inspect the page’s print CSS.
  • Paper size or scaling looks wrong: Check the CSS @page rules and PreferCSSPageSize choice, then adjust paper dimensions, margins, or scale.
  • Unexpected header or footer appears: Set the print method’s header/footer options explicitly, or use the CLI’s --no-pdf-header-footer flag.
  • The output file cannot be written: Check the working directory, permissions, and output path; handle file-write errors separately from browser errors.
  • The Chrome connection disappears: A lost browser connection can cancel the chromedp context. Check browser process health and ensure contexts are not canceled before the print action completes.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Reliability, performance, and cost considerations

Every conversion launches or uses a real browser and waits on page behavior, so workload time depends on navigation, scripts, resources, and the page’s readiness condition; the cited documentation does not establish a universal conversion speed or resource requirement. Reuse and lifecycle decisions should be made for your application’s concurrency and isolation needs, with explicit timeouts and error handling around navigation, printing, and file output.

On Linux, chromedp says it kills Chrome child processes it started when the program finishes. Its context also carries browser and tab state, and a lost browser connection can cancel that context. Defer cancellation and keep the context alive until all browser actions and PDF output collection have completed. chromedp repository and FAQ

Frequently asked questions

Does headless Chrome need a graphical desktop?

The Chrome CLI example uses headless mode, and chromedp documents a headless-shell option for headless environments. Deployment still needs a compatible browser executable and a runtime configuration that can launch it.

Can I use print CSS and CDP settings together?

Yes. Print CSS authors the document’s intended print layout, while CDP options control the browser’s print operation. The CSS page-size preference setting determines whether CSS page sizing is preferred over fitting content to the configured paper size.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Is a fixed delay enough to ensure a complete PDF?

No universal delay guarantees completion across sites. Wait for an application-specific readiness signal wherever possible; CLI timing flags likewise do not certify that all asynchronous rendering has finished.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

More from the Wire

  1. World desk4 min
    How to Spot an AI Voice Scam Before Sending MoneyDon’t rely on how a caller sounds. Pause, call back through a known number, and verify the emergency with another trusted person before sending money.
  2. Mountain View desk4 min
    Google’s SynthID Detector: How to Check AI-Generated Images, Video and AudioGoogle’s SynthID Detector looks for an embedded watermark in supported images, video and audio. Here is what its results do—and do not—show.
  3. Redmond desk20 min
    How to create a link to File or Folder in Windows 11Windows 11 gives you several ways to point to a file or folder without moving or duplicating it. You can create a desktop shortcut,…
Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.