ScreenshotRender
← Back to blog
Tutorials

How to Screenshot a Website From the Command Line

Robert Belt·8 min read
Updated On :
Illustration of a black terminal window filled with command lines beside a purple code bracket speech bubble on an orange background

Every guide to screenshotting a website from the command line gives you the same one liner and stops there. By the end of this you'll have that one liner, the three ways it quietly lies to you on real pages, and the single curl call that sidesteps all three.

Short answer: if Chrome is installed, run google-chrome --headless --screenshot=shot.png --window-size=1280,720 https://en.wikipedia.org/wiki/HTTP and you get a PNG in the current directory. That works. It also captures cookie banners, misses anything below the fold, and returns a challenge page instead of the site on bot protected domains. The rest of this covers each of those.

How do you take a screenshot of a website from the command line?

You pass a headless flag to a browser that is already on the machine. No install, no dependencies, no script file. Chrome and Firefox both ship this, and the syntax is a single line in each.

For Chrome or Chromium, the command above writes shot.png into the directory you ran it from. Headless Chrome boots the full rendering engine without a window, loads the URL, paints it, and writes the file. Firefox does the same thing with firefox --screenshot shot.png https://en.wikipedia.org/wiki/HTTP, and Firefox's headless mode captures the entire scrollable page by default rather than just the visible area.

That difference between the two matters more than it sounds, and it is the first thing that trips people up.

How do you get a full page screenshot from the terminal?

Use Firefox, or tell Chrome how tall the page is. Chrome has no full page flag: --screenshot captures the window, so whatever you set in --window-size is exactly what you get, and everything below the fold is simply absent from the file.

The common workaround is to pass an absurdly tall window, something like --window-size=1280,20000, then crop the blank space off the bottom afterward. It works often enough to be popular and is wrong often enough to be annoying, because you are guessing the page height before you have loaded the page. Guess short and you truncate the article. Guess tall and you get a strip of white you have to trim in a second tool. Firefox avoids the guess entirely by measuring the document itself, which is why it is the better default when you only need the whole page as an image. We compared this against the browser devtools and extension routes in our guide to capturing an entire webpage.

Height is the easy problem though. The harder one is that the image often does not look like the page you see in your own browser.

Why does your command line screenshot not match the real page?

Because a fresh headless browser has no history, no consent state, and a fingerprint that sites can spot. Your everyday browser has dismissed the cookie banner, loaded the images as you scrolled, and built up enough trust signals to be served the real page. A headless one launched seconds ago has none of that, so it captures a version of the site almost nobody actually sees.

Three things go wrong, in rough order of how often they bite:

  • Consent and cookie banners. The GDPR modal is the first thing rendered and it covers the content you wanted. Every capture from a clean browser profile gets one, because the browser has never accepted anything.
  • Content that has not loaded yet. Single page apps paint after the initial HTML arrives, and lazy loaded images only appear once something scrolls. A capture taken at load time gets an empty shell or a page full of placeholders.
  • Bot challenges. Point a headless browser at a bot protected site and you often screenshot the interstitial rather than the content. The command exits successfully and writes a valid PNG, which is what makes this one dangerous in a script. Nothing errors. You just archive the wrong image, sometimes for weeks, until someone opens one. We wrote up the mechanics of that in screenshotting a Cloudflare protected website.

You can fight all three from the command line. Chrome's --virtual-time-budget flag buys the page time to finish rendering, custom user agents and window sizes help a little with detection, and you can inject CSS to hide known banner selectors if you are willing to maintain a list of them per site. That is the honest ceiling of the built in flags: it is all guesswork you own forever.

Stop guessing window heights and banner selectors.

One curl call to ScreenshotRender returns a clean PNG with cookie banners, ads, and chat widgets already stripped, rendered on a real Chromium. 100 free screenshots, no credit card.

Get an API key

How do you take a command line screenshot with curl?

You point curl at a screenshot API, because curl itself cannot render anything. It is an HTTP client: it downloads the HTML a server hands over and never executes a line of JavaScript. The rendering has to happen somewhere, and with an API it happens on the other end of the request.

With ScreenshotRender the whole capture is one line you can paste into a terminal or a shell script: curl "https://screenshotrender.com/api/v1/screenshot?apiKey=YOUR_API_KEY&url=https://www.g2.com&fullPage=true"

That returns JSON with a hosted image URL at data.screenshot, along with the page title, description, favicon, and a tokensUsed count. Pipe it through jq -r .data.screenshot and you have a URL you can hand to another command. The parameters are the entire surface: url is the page, fullPage=true captures the whole scrollable document instead of the default 1280 by 720 viewport, wait takes a delay in seconds for pages that keep rendering after load, and timeout caps how long a render may take. When you do not pass wait, it defaults to two seconds.

The three failures from the last section are handled server side rather than by you. Cookie consent banners, ad overlays, and chat widgets are removed before every capture on every plan, including the free one, so there is no selector list to maintain. Full page is a parameter instead of a window height you guessed. And a failed render does not spend a credit, which matters when a script loops over a few thousand URLs and some of them are down. For bot protected pages, Stealth Mode on the Hobby plan and up renders past common challenges instead of archiving the interstitial.

Which command line screenshot tool should you use?

Pick based on whether the browser is already there and how much the output has to be trustworthy. There are five realistic options and they sort cleanly by effort:

  • Chrome headless. Already installed almost everywhere, zero setup, viewport only. Best for a quick look at a simple page.
  • Firefox headless. Same zero setup, but full page by default. The better of the two built ins when you want the whole document.
  • capture-website-cli. A Node.js wrapper around headless Chrome with real flags for full page, element clipping, delays, and hiding elements. Needs npm and it pulls a Chromium down, but it turns the guesswork into options.
  • wkhtmltoimage. Old, fast, and built on a dated WebKit that renders modern CSS poorly. Fine for simple or self authored HTML, misleading on anything current.
  • curl plus a screenshot API. No browser on your machine at all, and the banner, full page, and bot problems are solved on the server. The tradeoff is a per request cost and a network dependency.

For a one off glance at a page you control, the built in flags are genuinely the right answer and you should not overthink it. For anything that runs on a schedule and gets looked at later, the failure modes are what you are actually choosing between.

When does the command line approach fail?

It fails whenever the screenshot needs a session or an interaction. There is no flag for logging in, so anything behind auth is out of reach for a plain --screenshot call, and the same is true of pages that need a click, a form fill, or a scroll before the state you want exists. That is the line where you stop passing flags and start writing a Puppeteer or Playwright script, which can drive the page properly.

Two smaller limits worth knowing before you build on this. Fonts are the first: a headless browser on a bare Linux server usually has almost no font packages installed, so text renders in fallbacks and non Latin scripts come out as empty boxes. Concurrency is the second: each headless invocation is a full browser process, so a shell loop firing many at once will exhaust memory on a small machine well before you expect it.

None of that argues against the command line. It argues for knowing which of the three approaches you are in: flags for a quick look, a script when you need to interact, an API when the output has to be right without you watching it.

Common questions about command line screenshots

How do I take a screenshot of a website from the command line in Linux?

Use the headless flag on a browser you already have. On most Linux boxes that is google-chrome --headless --screenshot=shot.png --window-size=1280,720 followed by the URL, which writes a PNG into the current directory. Firefox works too with firefox --screenshot shot.png and the URL, and it captures the full scrollable page by default instead of just the viewport. Neither needs a package install if the browser is present.

Can Chrome take a full page screenshot from the command line?

Not with a dedicated flag. Chrome's --screenshot captures the window, so whatever you set with --window-size is what you get. The usual workaround is to pass a very tall window size and crop the empty space afterward, which is fragile because you have to guess the page height in advance. Firefox captures the full page by default, and screenshot APIs expose it as a parameter, so both avoid the guessing.

Can curl take a screenshot of a website?

Not on its own. curl is an HTTP client, so it downloads the HTML a server sends and never runs JavaScript or renders anything. To get an image from curl you point it at a screenshot API that renders the page on its side and returns the result. That is why a curl screenshot is one line: the rendering happens remotely and curl only carries the request and the response.

How do I wait for a page to load before taking a command line screenshot?

With Chrome, add --virtual-time-budget followed by a value in milliseconds, which lets the page run timers and fetches before the capture is written. It is a blunt instrument because you are guessing a duration rather than waiting for a specific element. Screenshot APIs usually expose the same idea as a parameter; ScreenshotRender takes a wait value in seconds and defaults to two seconds when you do not pass one.

Why is my headless Chrome screenshot blank or white?

Usually the capture fired before the page painted anything. Single page apps render after the initial HTML arrives, so a screenshot taken at load time catches an empty shell. Add a virtual time budget to give the page room, and check that the URL is not returning a redirect or a bot challenge instead of the site. A blank image and a challenge page look identical in an automated script, which is why it is worth opening the output before trusting it.

The rule that holds up: reach for the browser flags when you want to look at something once, and reach for a single HTTP call when the image has to be correct without anyone checking it. The one liner is not wrong, it just answers a smaller question than most scripts are really asking.

Keep reading