Use chromedp to drive Chrome or Chromium, navigate to the page, call Chrome DevTools Protocol’s Page.printToPDF method, and write the returned bytes to a PDF file. The browser is a separate prerequisite: chromedp controls it but does not bundle it.
Prerequisites and setup
- A current Go toolchain and a Go module.
- Chrome or Chromium installed and available to the process, or a compatible remote DevTools Protocol endpoint.
- The
chromedpGo package and itscdprotobindings.
From your module directory, add chromedp with go get github.com/chromedp/chromedp. The browser can run locally, in a Linux server or Docker-compatible container, on Windows or macOS, or at a remote DevTools endpoint. The project also identifies the chromedp/headless-shell container as an option for headless infrastructure; it is not required. See the chromedp project site for environment and setup guidance.
As an Amazon Associate I earn from qualifying purchases.
Convert a webpage to PDF
This complete example accepts the target URL and output path as command-line arguments, bounds browser work with a timeout, checks errors, and writes the PDF bytes returned by Chromium.
package main
import (
"context"
"fmt"
"os"
"time"
"github.com/chromedp/chromedp"
"github.com/chromedp/cdproto/page"
)
func main() {
if len(os.Args) != 3 {
fmt.Fprintln(os.Stderr, "usage: go run . <url> <output.pdf>")
os.Exit(2)
}
if err := convert(os.Args[1], os.Args[2]); err != nil {
fmt.Fprintln(os.Stderr, "convert:", err)
os.Exit(1)
}
}
func convert(targetURL, outputPath string) error {
ctx, cancel := chromedp.NewContext(context.Background())
defer cancel()
ctx, cancel = context.WithTimeout(ctx, 90*time.Second)
defer cancel()
var pdf []byte
err := chromedp.Run(ctx,
chromedp.Navigate(targetURL),
chromedp.ActionFunc(func(ctx context.Context) error {
var err error
pdf, _, err = page.PrintToPDF().Do(ctx)
return err
}),
)
if err != nil {
return fmt.Errorf("render page as PDF: %w", err)
}
if len(pdf) == 0 {
return fmt.Errorf("Chromium returned an empty PDF")
}
if err := os.WriteFile(outputPath, pdf, 0o644); err != nil {
return fmt.Errorf("write %q: %w", outputPath, err)
}
return nil
}
Run it with go run . https://example.com page.pdf. The process needs permission to write the destination path; adjust the file mode if your application requires different access. The timeout is an example bound, not a guarantee that every site will finish rendering within that interval.
#1 Best Overall
What the code does
chromedp.NewContextcreates an automation context. It does not launch Chrome immediately; the firstchromedp.Runallocates the browser if no parent context already has one.chromedp.Navigateopens the requested URL. Its completion alone does not prove that a site’s asynchronous content, fonts, or images have reached the desired state.page.PrintToPDF().Do(ctx)invokes CDP’s PDF printing method and returns PDF bytes.os.WriteFilesaves those bytes to the requested path.
In this standalone program the deferred cancellation calls stop the context and its browser work when the function returns. With nested chromedp contexts, cancellation closes a tab or the browser according to the context relationship; see the chromedp package reference.
Choose PDF print settings deliberately
The generated cdproto bindings expose controls for orientation, paper width and height, margins, scaling, page ranges, background graphics, headers and footers, header/footer HTML templates, CSS page sizing, transfer mode, tagged PDF, and document outlines. Consult the generated Page bindings for the API in the version you use; these bindings follow a moving browser protocol.
Rank #2
| Setting | What to decide | Documented default or behavior |
|---|---|---|
| Orientation | Choose portrait or landscape to suit the content. | Portrait. |
| Paper size and CSS sizing | Set explicit paper dimensions, or let the page’s print CSS define them. | preferCSSPageSize defaults to false; otherwise content is scaled to fit the paper. |
| Margins and scale | Specify margins and scale when the default layout is not suitable. | Available as print parameters; check the bindings for version-specific defaults. |
| Background graphics | Enable if colors or background images are part of the intended print layout. | Off. |
| Headers and footers | Enable and provide templates if you need page details. | Off. Templates can include date, title, URL, page number, and total pages. |
| Page ranges | Set ranges when only selected pages should be included. | Available as a print parameter; check the bindings for details. |
| Tagged PDF and outline | Enable when the output workflow calls for these document structures. | The tagged-PDF default is described as the embedder’s choice; consult the selected bindings for current behavior. |
For repeatable output, explicitly select the paper dimensions, orientation, and margins your use case needs. Also decide whether print CSS should control page size, and explicitly enable backgrounds or headers and footers when required. The exact setters and defaults can vary with the cdproto version and browser protocol, so inspect the bindings in your pinned dependency rather than assuming current main-branch behavior.
Wait for dynamic pages before printing
Navigation finishing is not a universal readiness signal. A client-rendered page may still be loading data, fonts, or images, and different sites expose different signs that their content is ready. Wait for a meaningful application state—such as a required element becoming visible—when the page needs it, rather than relying on an arbitrary fixed sleep. The chromedp project’s setup guidance recommends waiting for required state; no single condition is established as reliable for every website.
After capture, inspect the PDF for missing content, unexpected page breaks, clipped sections, or assets that had not loaded. Choose a readiness condition specific to the site and the content the PDF must contain.
Local browser, container, or remote endpoint
| Approach | When it can fit | Trade-off to account for |
|---|---|---|
| Local Chrome or Chromium | The host already has a browser binary and the Go process can launch it. | You manage the browser installation and its lifecycle. |
| Headless container | Your deployment runs compatible containers and you want a browser environment supplied as an image, such as chromedp/headless-shell. |
You still need to deploy and maintain that browser environment. |
| Remote DevTools endpoint | A compatible browser is available elsewhere and your process should connect to it. | Connectivity and endpoint lifecycle become part of the deployment. |
These are deployment choices, not measured performance or cost rankings. The chromedp project lists these environments but does not establish comparative throughput, resource use, or operating cost. In all cases, Chrome or Chromium remains separate from the Go automation library.
Rank #4
Troubleshooting
- Browser executable or connection error: Confirm Chrome or Chromium is installed and reachable by the process, or that the remote DevTools endpoint is available. Adding chromedp alone does not install a browser.
- The command times out: The page, browser startup, or remote connection may not complete within the context deadline. Check browser availability and connectivity, then set a bound that matches the job. For dynamic pages, wait on the needed application state rather than assuming navigation completion means rendering is finished.
- PDF is blank or missing content: Check whether the page renders asynchronously and whether the chosen readiness condition waits for the content you need. Open the PDF and inspect its page layout and loaded assets.
- Background colors or images are missing: Background printing is off by default. Enable the print option for background graphics in the bindings used by your version.
- Unexpected scaling or page size: Review paper dimensions and margins, and whether
preferCSSPageSizeshould be enabled for the site’s print CSS. - Output file cannot be written: Verify that the destination directory exists and that the process has permission to write there; check the error returned by
os.WriteFile. - Print parameters do not compile or behave as expected: Check the generated bindings for the specific
cdprotoversion in your module. Protocol APIs and generated bindings can move.
Or skip the browser setup
ScreenshotNeo can return a PDF from one GET request without requiring you to install or operate Chromium. It is a screenshot API and MCP server from Yorker Media; the PDF option is relevant when you want a hosted capture instead of managing the browser in this Go program. See the ScreenshotNeo API documentation for PDF parameters and response details.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
For a PDF response, use the PDF output option documented by ScreenshotNeo. ScreenshotNeo accepts cookie or consent banners as a visitor and removes more than 60 known consent platforms, newsletter popups, and chat widgets before capture; those steps can be turned off. Bot checks and CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; yearly billing gives two months free. Sign up for ScreenshotNeo’s free plan to get 1,000 screenshots a month with no card.
Best Value
Frequently Asked Questions
Does chromedp include Chrome or Chromium?
No. It is the Go automation layer; install a browser or connect to a compatible DevTools Protocol target.
Does navigation finishing guarantee the PDF contains all page content?
No. Dynamic pages can still be loading application data or assets, so wait for a page-specific readiness condition when needed.
Can the website’s print CSS set the PDF page size?
Yes. The CDP print option preferCSSPageSize controls whether CSS page sizing is preferred; its documented default is false.
Quick Recap
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.




