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 DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
browser automation

How to Take Full-Page Screenshots in Go with chromedp

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

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

The shortest Go solution is chromedp.FullScreenshot. Run Chrome or Chromium through chromedp, navigate to the page, wait for that page’s content to finish rendering, call FullScreenshot(&buf, 100), and write the returned bytes to a file. Quality 100 produces PNG; any other value from 0 through 100 produces JPEG.

A full-page capture is different from a viewport screenshot: it includes content below the fold by using Chrome DevTools’ beyond-viewport capture. The important caveats are dynamic content readiness and device emulation, because the documented action can override emulation settings.

Set up Go, chromedp, and a Chrome runtime

chromedp controls Chrome through the DevTools Protocol, so a Chrome or Chromium executable must be available on the machine running your program. Add the package to a Go module:

go mod init example.com/fullshot
go get github.com/chromedp/chromedp

The package does not download a browser for you. In a local development environment, install Chrome or Chromium using your operating system’s normal package or installer, then verify that it can launch under the account that will run the Go program. In containers or CI, also check sandbox and shared-memory settings before diagnosing the screenshot code itself.

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

Minimal full-page screenshot in Go

This complete program navigates to a page, waits for a page-specific element, pauses briefly for client-side rendering, captures the entire page, and saves a PNG:

package main

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

    "github.com/chromedp/chromedp"
)

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

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

    var buf []byte
    err := chromedp.Run(ctx,
        chromedp.Navigate("https://example.com"),
        // Replace #app with a selector that means your page is usable.
        chromedp.WaitVisible("#app", chromedp.ByQuery),
        chromedp.Sleep(500*time.Millisecond),
        chromedp.FullScreenshot(&buf, 100),
    )
    if err != nil {
        log.Fatal(err)
    }

    if err := os.WriteFile("full-page.png", buf, 0o644); err != nil {
        log.Fatal(err)
    }
}

Run it with go run .. The result is full-page.png in the current directory. If the target has no #app element, replace that selector with a stable element such as main, a page-specific heading, or another marker that appears only after the application has rendered.

Why FullScreenshot captures below the fold

A normal viewport screenshot captures only the pixels currently visible in the browser window. chromedp.FullScreenshot is the dedicated action for an entire browser viewport/page capture. Internally, Chrome DevTools uses beyond-viewport capture, so the returned image can include the page’s scrollable content rather than stopping at the initial window height.

Use chromedp.Screenshot(selector, &buf, ...) when you need one DOM element instead. That operation is intentionally different: it crops to the selected element rather than producing a page-length image.

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

Wait for dynamic content before capturing

Navigation finishing is not a universal definition of “ready.” A single-page app can still be fetching data, a chart can still be drawing, and images may be deferred until they approach the viewport. Choose a readiness condition for the application you are capturing.

Wait for a stable selector

chromedp.WaitVisible is useful when a known element appears only after the main render completes. Prefer a selector tied to the page’s actual content rather than a generic loading wrapper that exists from the beginning.

Use a short, deliberate delay when rendering continues

After the readiness selector appears, a small chromedp.Sleep can allow animations, fonts, or chart canvases to settle. Keep this delay explicit and measured for your application; there is no universal chromedp wait that guarantees every framework has finished.

Handle lazy-loaded sections

If content is loaded only after scrolling, make it render before calling FullScreenshot. A practical approach is to scroll through the page with JavaScript actions, wait for the last section or image to become visible, and then capture. If the page has a “load more” control, click it first and wait for the newly inserted selector. The screenshot action cannot include DOM content that the page has not rendered.

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

Wait for network-idle policies carefully

Some applications keep analytics, sockets, or polling requests open indefinitely. A network-idle rule can therefore wait forever or become a poor proxy for visual readiness. A page-specific selector plus a bounded timeout is usually easier to reason about, with a separate delay only where the UI needs it.

Choose PNG or JPEG with the quality argument

The documented quality range is 0–100:

Quality argument Output When to use it
100 PNG Lossless text, diagrams, interfaces, and visual evidence
0–99 JPEG Smaller files when some compression is acceptable; the value is passed to Chrome as JPEG quality

For a JPEG, change only the quality argument and the filename:

chromedp.FullScreenshot(&buf, 80)
// write buf to full-page.jpg

Do not assume a low quality value still produces PNG. The format switch is part of the documented behavior: 100 selects PNG, while every other valid value selects JPEG.

Viewport, device emulation, and page dimensions

FullScreenshot can override device emulation settings. If you configure a mobile device, custom viewport, or device scale factor and the output does not match those assumptions, inspect the actual image rather than trusting the emulation configuration alone. The official example specifically warns that FullScreenshot overrides the device’s emulation settings.

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

For reproducible captures:

  • Set the viewport and device settings deliberately before navigation.
  • Keep the same browser, viewport, and scale-factor configuration across runs.
  • Verify the resulting dimensions and responsive layout with a sample capture.
  • Do not treat a full-page image as proof that a mobile device’s exact screenshot pipeline was preserved; the full-page action can change those settings.

Very long pages can produce large in-memory byte slices. Write the bytes promptly, avoid retaining many captures at once, and choose JPEG when the use case permits smaller output. No universal maximum page height or capture time is established here; the practical limit depends on the page, browser process, available memory, and output size.

Make the capture reliable in automation

Bound every browser job

Wrap the chromedp context in a timeout, as the example does. This prevents a broken navigation or never-ending readiness condition from consuming a worker indefinitely. Log the URL and the failed action so a timeout can be distinguished from an invalid selector or a browser-launch problem.

Keep readiness deterministic

Use a selector, known render event, or explicit application state that your team controls. A fixed delay alone is easy to write but can be too short on a busy runner and unnecessarily slow on a fast one.

Control page state

Authentication, consent dialogs, feature flags, and geolocation can change the DOM before capture. Configure those conditions before the screenshot action and make them part of the job’s documented inputs. If an overlay is expected, dismiss it before capture rather than trying to crop it out afterward.

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

Store useful diagnostics

On failure, retain the URL, timeout, browser stderr, and the readiness selector. A small viewport screenshot or page log taken before the full capture can show whether the problem is navigation, rendering, or the full-page action itself.

Troubleshooting common failures

The image stops at the visible window

Cause: the code used a viewport or element screenshot action. Fix: call chromedp.FullScreenshot(&buf, quality) after the page is ready.

The page is blank or missing application content

Cause: capture ran immediately after navigation, before client-side rendering completed. Fix: wait for a meaningful selector, add an application-specific settling delay, and confirm that the selector actually appears on the failing URL.

Images or lower sections are absent

Cause: lazy loading has not been triggered. Fix: scroll through the page or otherwise activate the page’s loading condition, wait for the final section or image, then capture.

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

The file format is unexpected

Cause: a quality value below 100 selects JPEG. Fix: use quality 100 for PNG, or use a JPEG extension and an intentional value such as 80.

The output does not match mobile emulation

Cause: FullScreenshot can override device emulation settings. Fix: verify the resulting viewport and layout, then adjust your capture design around the action’s documented behavior rather than assuming emulation survives unchanged.

Chrome will not start

Cause: no usable Chrome/Chromium runtime is installed, or the execution account cannot launch it. Fix: install a supported browser runtime, test it under the same account and container as the Go process, and resolve sandbox or permission errors before changing screenshot code.

The job times out

Cause: navigation, a selector, a network request, or rendering never completed. Fix: keep the timeout bounded, identify which action is waiting, replace generic network-idle assumptions with a page-specific readiness test, and capture a diagnostic log.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

chromedp and Playwright: which model fits?

Playwright defines a full-page screenshot as the full scrollable page and exposes fullPage: true (or full_page=True in Python-style APIs). In Go, chromedp is the direct, package-native route when you already operate a Chrome DevTools workflow.

Decision point chromedp Playwright
Go API Go package with chromedp.FullScreenshot Use a Playwright binding; the cited full-page option is fullPage/full_page
Full-page semantics Captures beyond the visible viewport through Chrome DevTools Captures the full scrollable page
Output control documented here Quality 100 selects PNG; other valid values select JPEG Format controls are not specified in the cited material
Emulation caveat FullScreenshot can override device emulation settings Not stated in the cited material
Readiness You supply the selector, delay, or other application-specific condition You still need an application-specific readiness strategy

There is no benchmark here that proves one library is faster or more reliable for every site. Choose based on the language, browser lifecycle you already operate, and how much control you need over Chrome DevTools behavior.

Or skip the browser setup

ScreenshotNeo is the alternative to try first when you want an HTTP screenshot service instead of managing Chrome in Go: it removes cookie and consent banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed; and every response identifies the result with X-Page-Verdict and X-Billed headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.

One GET request returns PNG, JPEG, WebP, or PDF. The API supports full-page capture with lazy images loaded, CSS-selector element capture, dark mode, 12 device presets plus custom viewports, retina scale, PDF paper size/margins/orientation/page ranges, custom CSS and JavaScript, clicks before capture, selector waits, delays or network-idle waits, ad/tracker/request/resource blocking, custom headers/cookies/user agents/Authorization, timezone and geolocation, transparent backgrounds, image resizing, configurable caching TTLs, signed public-image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API, and an OpenAPI specification. Common screenshot-API parameter names are accepted to ease migration.

Free tools Windows power users keep installed

One-click scans. No signup required.

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

See the ScreenshotNeo API documentation for authentication and options. The following examples use the supplied endpoint and target URL:

cURL

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

Python

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

Node.js

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' }); const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

Plans

Plan Included shots Listed price
Free 1,000 per month $0; no card
Starter 3,000 $5
Growth 15,000 $15
Pro 60,000 $39
Scale 250,000 $99
Business 1,000,000 $249

Every feature is available on every plan, and yearly billing gives two months free. Create a free ScreenshotNeo account to get 1,000 screenshots each month without adding a card.

Frequently Asked Questions

Can a full-page image include content revealed by a button click?

Yes, but the click must happen before FullScreenshot. Add the click as a chromedp action, wait for the newly inserted or expanded content, and then capture.

Does FullScreenshot return image bytes or a filename?

It writes the encoded image into the []byte buffer you provide. Your Go code decides whether to write those bytes to disk, upload them, or process them in memory.

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

Can I use the same approach for a PDF?

This chromedp action produces an image. A PDF requires a separate browser print-to-PDF workflow; use ScreenshotNeo’s capture_pdf tool or PDF API option when you want a service endpoint instead.

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.

Read next

Recommended PC Tool
Recommended PC Tool
Crashes, No Sound, or Screen Glitches?Free driver scan
PC Slower Than It Used to Be?Free scan - under a minute

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.