Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →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.
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.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →- 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
naturalWidthof zero, so the success predicate remains false. Identify the failed resource or define a timeout and an explicit policy for failed images rather than treatingcompletealone 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.imagesdoes 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:
FullScreenshotoverrides 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.Runbefore writing, then check the separateos.WriteFileerror 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.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.
Rank #4
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.
Quick Recap
Best Value
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.

