What Is a True Headless Browser?

Pierre Tachoire

Pierre Tachoire

CTO

What Is a True Headless Browser?

TL;DR

Most “headless” browsers aren’t really headless. They’re just regular consumer browsers running with the display turned off. A true headless browser skips all the graphical rendering, building only what programs need (the DOM tree) while ignoring everything designed for human eyes (images, fonts, CSS layout). This approach can reduce resource usage by 60-80% for automation workloads.

What “Headless” Usually Means

When you launch Chrome with the --headless flag, Chrome starts up completely, loads its entire rendering engine, processes CSS, downloads fonts and images, calculates layouts, paints pixels to framebuffers.

# launching "headless" Chrome $ google-chrome --headless

This made sense when headless mode was created. The Chrome team took their existing codebase and added a flag to skip displaying the window. Minimal code changes, maximum compatibility. Every website that works in regular Chrome works in headless Chrome because it’s literally the same browser.

But for automation it’s massive overkill.

What Programs Actually Need

Let’s break down what happens when a browser loads a web page:

  1. Fetch HTML over the network
  2. Parse HTML into a DOM (Document Object Model) tree
  3. Fetch and execute JavaScript that manipulates the DOM
  4. Fetch and parse CSS to apply styling rules
  5. Calculate layout (where everything goes on screen)
  6. Fetch images and fonts for display
  7. Paint pixels to render the visual result
  8. Composite layers for smooth scrolling and animations

Automation scripts only interact with steps 1-3. You navigate to a page, you query the DOM for elements, you interact with those elements through JavaScript.

// What your automation actually does await page.goto('https://example.com'); // Step 1-3 const price = await page.$eval('.price', el => // Step 3 (DOM query) el.textContent ); await page.click('#buy-button'); // Step 3 (DOM interaction)

Steps 4-8 exist entirely for human eyeballs. A program doesn’t care about the exact button’s position, whether the font is Arial or Helvetica, or if there’s a smooth fade-in animation. The program just needs to know the button exists in the DOM and can be clicked.

The Real Cost of Rendering

CSS Processing

CSS parsers convert stylesheets into rule trees. Layout engines calculate positions, sizes, margins, and paddings for every element. For a typical e-commerce page with 2,000+ DOM nodes and hundreds of CSS rules, this becomes serious computation.

Your automation script doesn’t care if the price is positioned 20 pixels from the top or 200 pixels. It just needs <span class="price">$29.99</span> from the DOM.

Image Decoding

Modern web pages load dozens of images: product photos, logos, icons, background images. Chrome downloads them, decodes JPEG/PNG/WebP formats into pixel data, and stores them in texture memory.

For automation extracting text data, every image download is wasted bandwidth and every decoded image is wasted bandwidth, time and memory.

Font Loading

Web fonts have become standard. A single page might load 3-4 font files totaling several megabytes. Chrome downloads them, parses the font metrics, and prepares glyph rendering.

Your scraper reading <h1>Product Name</h1> only needs the text content, not the custom typeface.

Layout Calculation

This is where Chrome figures out where every box goes on screen. It’s complex: flexbox, grid, floats, absolute positioning, responsive breakpoints. The engine recalculates layouts when the DOM changes or the window resizes.

Automation doesn’t need real x/y coordinates. It queries elements by selectors and reads their attributes.

What Does “True Headless” Mean?

A true headless browser builds only what programs need: the DOM tree and JavaScript execution environment. Here’s what Lightpanda does differently:

ChromeLightpanda
Fetch HTML over the networkYesYes
Parse HTML into a DOM treeYesYes
Fetch and execute JavaScript that manipulates the DOMYesYes
Fetch and parse CSS to apply styling rulesYesNo
Calculate layoutYesNo
Fetch images and fonts for displayYesNo
Paint pixels to render the visual resultYesNo
Composite layers for smooth scrolling and animationsYesNo

The result is a DOM tree in memory that your automation can interact with through standard APIs. When you call document.querySelector('.price'), you get the element. When you call element.textContent, you get the text. The DOM exists but the visual rendering doesn’t.

// Same automation code, different engine const browser = await puppeteer.connect({ browserWSEndpoint: 'ws://127.0.0.1:9222 // Lightpanda endpoint }); // This works identically const page = await browser.newPage(); await page.goto('https://example.com'); const price = await page.$eval('.price', el => el.textContent);

The DOM tree structure is identical. The JavaScript execution works the same but under the hood, Lightpanda never downloads a single font or image and never calculates a single layout dimension.

What You Give Up

Lightpanda makes tradeoffs. You need to understand what you’re giving up:

No Visual Regression Testing

You can’t take screenshots of pages that aren’t rendered. If you need to verify that button’s exact position or that an image displays correctly, you need actual rendering.or

Lightpanda uses the same API as Chrome (CDP). This means you can run the same script in your workflows if you need to take a screenshot at buildtime, but not every time you extract the data or take an action on the page.

No Layout-Dependent Interactions

Some interactions depend on visual layout. “Click the element at coordinates (100, 200)” requires knowing where things are positioned. “Click the third visible item” requires knowing which items are actually visible based on CSS display properties.

Lightpanda handles selector-based interactions fine: “click the button with class ‘submit’” works because that’s a DOM query. Coordinate-based interactions don’t work because there are no real coordinates.

When to Use Lightpanda

Here’s our recommended decision framework:

Use Lightpanda when:

  • Extracting data (scraping, monitoring, indexing)
  • Running functional tests that check behavior, not appearance
  • Automating form submissions and workflows
  • Generating reports from web-based dashboards
  • Running at scale where resource costs matter

Use Headless Chrome when:

  • Taking screenshots or PDFs
  • Visual regression testing
  • Testing responsive design breakpoints
  • Debugging layout issues
  • Working with sites that absolutely require rendering

Use Headful Chrome when:

  • Developing and debugging automation scripts
  • Need to see what’s happening in real-time
  • Testing actual user experience

Ready to Experience What a True Headless Browser Feels Like?

Making the Switch

If you’re currently using Puppeteer or Playwright with Headless Chrome, switching to Lightpanda requires minimal code changes. The Chrome DevTools Protocol (CDP) compatibility means your automation scripts mostly work as-is.

Start by testing your automation suite against Lightpanda in a development environment. For scripts that don’t work, you can run hybrid setups and fallback to Chrome when you need rendering.

Ready to try it?