Halloween DealsAmazon USHalloween week deals: useful picks before month-endAmazon US: current deals, useful picks and tech finds.Check DealsSlow PC?RecommendedPC slow today? Run a repair scan before it gets worseResolve common Windows issues and optimize system performance.Scan NowHalloween DealsAmazon USOctober picks are moving - compare before checkoutAmazon US: current deals, useful picks and tech finds.See Picks×
FREEDOM251

Freedom251 › Blog › browser automation

Capture a Website Screenshot in Go with chromedp and Wait for Images to Load

By Freedom251 Team · · 4 min read

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

Navigate to the page, wait on an explicit JavaScript predicate for the relevant <img> elements, and then capture the viewport, an element, or the full page. chromedp.WaitReady and WaitVisible report DOM state; they do not guarantee that page images have loaded.

Wait for successful image loads before capturing

Use chromedp.Poll to wait until each current image element is complete and has a positive natural width. The predicate below treats broken images as not successfully loaded.

As an Amazon Associate I earn from qualifying purchases.

const imagesLoaded = `Array.from(document.images).every(img => img.complete && img.naturalWidth > 0)`

if err := chromedp.Run(ctx,
    chromedp.Navigate(url),
    chromedp.Poll(imagesLoaded, nil),
    chromedp.FullScreenshot(&buf, 100),
); err != nil {
    return err
}

HTMLImageElement.complete alone is not a success check: it can also be true when an image has no source or failed to load. Requiring naturalWidth > 0 excludes those cases. This predicate checks images present in document.images when it is evaluated; it does not establish that every visual asset on a page has settled.

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

Build and run a complete Go example

Install chromedp in your Go module with go get github.com/chromedp/chromedp. The example below navigates to a URL, waits for successful current <img> loads, captures the full page as PNG, and writes the bytes only after the browser actions succeed.

package main

import (
    "context"
    "fmt"
    "os"

    "github.com/chromedp/chromedp"
)

func main() {
    if len(os.Args) < 2 {
        fmt.Fprintln(os.Stderr, "usage: go run . URL")
        os.Exit(2)
    }
    url := os.Args[1]

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

    var buf []byte
    const imagesLoaded = `Array.from(document.images).every(img => img.complete && img.naturalWidth > 0)`

    err := chromedp.Run(ctx,
        chromedp.Navigate(url),
        chromedp.Poll(imagesLoaded, nil),
        chromedp.FullScreenshot(&buf, 100),
    )
    if err != nil {
        fmt.Fprintln(os.Stderr, "capture failed:", err)
        os.Exit(1)
    }

    if err := os.WriteFile("page.png", buf, 0644); err != nil {
        fmt.Fprintln(os.Stderr, "write page.png:", err)
        os.Exit(1)
    }
}

Save this as main.go, then run go run . https://example.com from its module directory. FullScreenshot with quality 100 produces PNG; other supported quality values produce JPEG. Check the returned error before writing, so a failed navigation, wait, or capture is not mistaken for a valid file.

Choose the capture that matches the output you need

Target chromedp action Notes
One element chromedp.Screenshot(selector, &buf, ...) Captures the selected element. The official example writes the resulting bytes to a file with os.WriteFile.
Full page chromedp.FullScreenshot(&buf, quality) Captures the full page; quality 100 yields PNG, while other supported values yield JPEG. This action overrides device emulation settings.
Current viewport chromedp.CaptureScreenshot(&buf) Captures the current viewport.
Custom clip or protocol-level options Use the generated Page protocol screenshot API The API exposes format, quality, clipping, surface capture, and capture-beyond-viewport parameters.

Keep the wait action before the capture action in the same chromedp.Run sequence. If viewport or mobile emulation matters, account for the fact that FullScreenshot overrides device emulation settings; choose a viewport or protocol-level capture flow when that behavior does not suit the intended image.

Account for lazy images and non-image assets

The predicate is a practical baseline for current DOM <img> elements, not a universal page-settled signal. Lazy images below the fold may not begin loading until scrolling brings them into view. A page may also render visual content using CSS background images, canvas, or application code; those assets are not covered by document.images.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  • For lazy-loaded content, trigger the page’s intended loading behavior, such as scrolling through the relevant region, before the final wait and capture.
  • For application-rendered or CSS-based imagery, wait for a site-specific readiness signal or inspect the relevant resources separately.
  • If a broken image should not block capture, change the condition to reflect that policy; the supplied success predicate deliberately waits for a positive naturalWidth.

There is no single documented chromedp wait that covers every lazy-loading strategy, background image, canvas, or app-specific rendering pattern.

Troubleshoot captures that hang or miss content

  • The wait never finishes: a broken image has naturalWidth of zero, so the success predicate remains false. Identify the failed resource or define a timeout and an explicit policy for failed images rather than treating complete alone as success.
  • The screenshot is missing images below the fold: lazy loading may not have started before capture. Scroll through the content that should appear in the image, then wait again for the relevant assets.
  • The screenshot misses a background or canvas image: document.images does not cover those drawing paths. Wait for an application-specific signal or inspect those resources separately.
  • An element screenshot fails or captures the wrong region: confirm the selector identifies the intended element and that it exists in the page before calling chromedp.Screenshot. Element readiness and visibility are separate from image completion.
  • The full-page result has unexpected emulation dimensions: FullScreenshot overrides device emulation settings. Use a capture method suited to the viewport or configure the protocol capture parameters for the target.
  • No output file appears: propagate and inspect the error from chromedp.Run before writing, then check the separate os.WriteFile error and destination path.

Or skip the browser setup

ScreenshotNeo provides a website screenshot API and MCP server. A single GET request can return a screenshot or PDF; this cURL example saves a WebP screenshot:

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

See the ScreenshotNeo API documentation for request options. It removes cookie banners, newsletter popups, and chat widgets before capture; bot checks, blank pages, and failed loads are never billed. Its MCP server lets AI agents take screenshots, and the free plan includes 1,000 screenshots per month with no card required; paid plans start at $5 for 3,000. Sign up free for ScreenshotNeo.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Frequently Asked Questions

Does WaitVisible mean all images are loaded?

No. It reports visibility of a DOM element, not successful loading of every page image. Use an image predicate when that condition matters.

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

Why check naturalWidth as well as complete?

A complete image can still be broken or have no source. A positive naturalWidth provides a practical check that the image has intrinsic image data.

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.

browser automationchromedpGoweb screenshots

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.

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.