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

For an existing local HTML file, navigate Puppeteer to that file’s absolute file: URL; the browser can then resolve a relative stylesheet such as ./styles.css from the HTML file’s directory. If you instead call page.setContent(), you are assigning markup, not opening a file, so put the CSS in the markup or attach the stylesheet with page.addStyleTag().

Load a stylesheet by navigating to the local HTML file

Use this approach when you already have an HTML document and want its linked CSS, images, fonts, scripts, and other relative assets to load as they would from that document. Resolve the HTML path to an absolute path, convert it to a file URL, then pass that URL to page.goto().

import puppeteer from 'puppeteer';
import {resolve} from 'node:path';
import {pathToFileURL} from 'node:url';

const browser = await puppeteer.launch();

try {
  const page = await browser.newPage();
  const htmlPath = resolve('./public/index.html');
  const fileUrl = pathToFileURL(htmlPath).href;

  console.log('Loading:', fileUrl);
  await page.goto(fileUrl);

  await page.screenshot({path: 'page.png', fullPage: true});
} finally {
  await browser.close();
}

In this example, the file public/index.html can link to a stylesheet beside it:

<link rel="stylesheet" href="./styles.css">

That relative href is resolved from the HTML document’s location, not from the directory where you ran Node.js. If the CSS is instead in public/css/site.css, write href="./css/site.css". A correct absolute HTML path is not enough if the href itself points to the wrong place.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Elebase USB to USB C Adapter for iPhone 18 Pro Max,USBC Car Charger Adapter
  • Read Before You Buy — No Video Output: These adapters support charging and USB 2.0 data transfer, but cannot transmit video signals. Except for standard USB webcams (which use USB data only), they are not compatible with HDMI/DisplayPort cables, video-capable USB-C hubs, or docking stations with video output.
  • Convert USB-A Ports to USB-C: Designed to connect USB-C earphones, cables, flash drives, card readers, and other USB-C accessories to standard USB-A ports. Plug-and-play with no drivers or software required.
  • Aluminum Alloy Housing: Built with a sturdy aluminum alloy shell that aids in heat dissipation and protects against daily wear and scratches. Designed to maintain a stable and secure connection.
  • Compact & Travel-Friendly: The ultra-compact design allows the adapter to stay plugged into your device without blocking adjacent ports or adding bulk, reducing wear and tear on your original USB ports.
  • 12-Month Warranty: Backed by a 12-month manufacturer warranty for peace of mind. Designed to meet strict quality control standards for reliable everyday performance.

pathToFileURL() handles conversion from a filesystem path to a properly encoded file URL, including path separators and special characters. Resolving the path explicitly also makes the script’s current-working-directory assumption visible: resolve('./public/index.html') is relative to the process working directory.

Wait for a meaningful render condition

page.goto() performs navigation, but a page that applies styles dynamically or loads assets asynchronously may need an additional wait before capture. Prefer waiting for something that demonstrates the page is ready, such as a known element or a computed style, rather than adding an arbitrary long pause.

await page.goto(fileUrl);
await page.waitForSelector('#report-ready');

const background = await page.$eval(
  '#report-ready',
  element => getComputedStyle(element).backgroundColor
);
console.log('Ready element background:', background);

await page.screenshot({path: 'page.png'});

Replace #report-ready with a selector that exists in your document. If there is no suitable element, check a specific computed style with page.waitForFunction(). The Puppeteer Page API has navigation, waiting, and stylesheet-injection methods; confirm available methods against the version installed in your project.

Rank #2
Anker USB-C Hub, 5-in-1 USB Hub for Laptops, 4K HDMI Multiport Adapter
  • 5-in-1 USB-C Hub: Experience comprehensive connectivity featuring a Power Delivery input, two USB-A 2.0 ports, a USB-A 3.0 port, and an HDMI port. (Note: The USB-C power delivery input port is only for connecting an external wall charger to power your laptop and cannot power peripheral devices.)
  • 90W Pass-Through Charging: Achieve optimal charging with 90W pass-through power to your laptop, supported by a total input of 100W, with the hub reserving 10W for operational efficiency. (Note: Wall charger not included.)
  • Quick Data Transfers: Accelerate your productivity with rapid data transfers using a high-speed 5Gbps USB 3.0 port and two 480Mbps USB 2.0 ports.
  • 4K HDMI Display: Enhance your visual experience with a hub capable of delivering 4K resolution at 30Hz in both mirror and extend modes. Please note that this hub is compatible with MacBook (macOS 12 and newer), Windows 10 and 11, ChromeOS, and laptops equipped with DP Alt Mode and Power Delivery. Note: This device is not compatible with Linux.
  • What You Get: Anker USB-C Hub (5-in-1, 4K HDMI), welcome guide, 18-month warranty, and our friendly customer service.

Choose the right method for your HTML source

What you have Use Why
An HTML file on disk with relative assets page.goto(pathToFileURL(absolutePath).href) The browser loads the document at its file URL, giving relative links a file-based location.
A short HTML string or generated markup page.setContent(html) with a <style> element Useful for self-contained markup that does not depend on a directory of sibling assets.
Generated markup and a separately maintained local CSS file page.setContent(html), then page.addStyleTag({path: absoluteCssPath}) Keeps the markup and stylesheet separate without navigating to an HTML file.

Set generated markup and add CSS explicitly

page.setContent() sets the page’s HTML markup; it does not interpret a filesystem path as a document to open. For a small fixture, the simplest solution is a style element in the markup:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
const html = `
  <!doctype html>
  <html>
    <head>
      <style>
        body { font: 16px sans-serif; }
        .ready { color: darkgreen; }
      </style>
    </head>
    <body><main class="ready">Hello</main></body>
  </html>
`;

await page.setContent(html);
await page.screenshot({path: 'generated.png'});

When the stylesheet is stored separately, attach it by absolute path after setting the markup:

import {resolve} from 'node:path';

await page.setContent('<main class="ready">Hello</main>');
await page.addStyleTag({path: resolve('./public/styles.css')});
await page.screenshot({path: 'generated.png'});

addStyleTag() can add a stylesheet link or a style element. The path option is handy for a CSS file on disk. If the markup depends on relative images, fonts, or scripts as well as CSS, navigating to an actual HTML file is usually the clearer choice: it gives those resources a document URL and a consistent base for relative paths.

Rank #3
Sale
Anker USB C Hub, 7in1 Multi-Port USB Adapter, 4K@60Hz USBC to HDMI Splitter
  • Sleek 7-in-1 USB-C Hub: Features an HDMI port, two USB-A 3.0 ports, and a USB-C data port, each providing 5Gbps transfer speeds. It also includes a USB-C PD input port for charging up to 100W and dual SD and TF card slots, all in a compact design.
  • Flawless 4K@60Hz Video with HDMI: Delivers exceptional clarity and smoothness with its 4K@60Hz HDMI port, making it ideal for high-definition presentations and entertainment. (Note: Only the HDMI port supports video projection; the USB-C port is for data transfer only.)
  • Double Up on Efficiency: The two USB-A 3.0 ports and a USB-C port support a fast 5Gbps data rate, significantly boosting your transfer speeds and improving productivity.
  • Fast and Reliable 85W Charging: Offers high-capacity, speedy charging for laptops up to 85W, so you spend less time tethered to an outlet and more time being productive.
  • What You Get: Anker USB-C Hub (7-in-1), welcome guide, 18-month warranty, and our friendly customer service.

Or skip the browser setup

If your target is a published, reachable webpage rather than a file that exists only on your computer, ScreenshotNeo can return a screenshot or PDF from one GET request. A remote screenshot service cannot read a path on your machine such as ./public/index.html; publish the page at a URL the service can reach first. For a publicly reachable page, the cURL request is:

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

See the ScreenshotNeo API documentation for request options. The product removes cookie and consent banners, newsletter popups, and chat widgets before capture; each of those cleanup steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and responses identify page verdict and billing status in headers. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents using Claude, Cursor, or another MCP client. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 shots.

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.

Sign up for 1,000 free screenshots a month, with no card required.

Troubleshoot missing or unapplied CSS

  1. Confirm the document URL. After navigation, log page.url(). It should be the intended absolute file: URL, not a relative string or a different file than expected.
  2. Check which directory your path starts from. Log the result of resolve('./public/index.html'). Node resolves that path from the process working directory, which may differ from the script’s directory when a test runner, IDE, or package script launches it.
  3. Verify the stylesheet href and its location. Check the spelling of rel="stylesheet", the href, and the actual CSS file path. A relative href is interpreted from the document URL, so moving the HTML file can break a path that used to work.
  4. Try injecting the CSS as a diagnostic. Call page.addStyleTag({path: resolve('./public/styles.css')}). If the CSS then appears, the stylesheet itself may be valid; investigate the HTML link’s relative path or spelling.
  5. Inspect console messages and failed requests. These can reveal missing files or browser errors. If you enabled request interception, make sure every intercepted request is continued, fulfilled, or aborted. Puppeteer warns that an intercepted request stalls until one of those actions occurs or the request finishes from cache.
  6. Wait for the actual rendering condition. If styles or assets are applied asynchronously, wait for a selector, a delay only when genuinely needed, or another meaningful condition before taking the screenshot. A screenshot taken too early can capture an intermediate state.
  7. Investigate CSP only if a policy is present. Content Security Policy can prevent style application in some setups. Puppeteer’s CSP-bypass setting takes effect at policy initialization and generally needs to be enabled before navigation. It is not a general fix for a wrong file path or href.
  8. Change the loading model only when there is evidence of a file-access restriction. If the browser reports that local access is blocked, serving the files from a controlled local HTTP server may be an option. That changes the document origin and can affect scripts, fetches, and origin-dependent behavior, so it is not a drop-in equivalent to file: navigation.

Avoid broad Chrome security-disabling flags as a first response to ordinary path mistakes. First identify the concrete browser error and the resource URL that failed; browser behavior can vary with the installed browser and launch environment.

Rank #4
Sale
UGREEN USB to USB C Adapter Combo 4-Pack, 10Gbps USB C Converter Space Gray
  • Dual Converters, Infinite Potential:Includes 2× USB C male to USB A female adapters and 2× USB A male to USB C female adapters. Perfect for a wide range of uses—tablets with Bluetooth keyboards, expand USB ports on macbook, and more. Two different converters for all your daily needs
  • Next-Level 10Gbps & 3A Charging: No more slow 480Mbps, this usb to usb c adapter has a transfer speed of up to 10Gbps, allowing you to do more transferring in less time. This usb adapter fits both USB A and USB C charger, supporting up to 3A fast charging
  • Upgraded Exquisite Craftsmanship: With an aluminum alloy housing and metal connector, the usbc to usb adapter is extremely durable and sturdy. Rigorously tested to withstand more than 10,000 times of plugging and unplugging, ensuring long-lasting performance
  • Broad Compatible: The usb c to usb adapter widely supports all USB C/ USB A devices like laptops, tablets, cellphones, car chargers, and phone chargers. Such as compatible with MacBook Pro/Air 2023/2022, Thunderbolt 4/3 Devices,Apple MagSafe Watch 9/8/7/SE/Ultra, iPad Pro 2022/2021, Samsung Galaxy S23/S20/S10, and iPhone 17/16/15 Pro. Plug and play
  • Please Note: To reach 10Gbps speed, keep the cable under 3.3 ft. For USB A Male to USB C adapters, try flipping the USB C connector. USB C Male to USB A adapters support bidirectional 10Gbps transfer within 3.3 ft
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Keep captures reliable and diagnose version differences

Make the working directory and browser explicit

Log the absolute HTML and CSS paths when diagnosing a failure. This makes it easier to distinguish a Puppeteer issue from a script launched in an unexpected directory. If you use a custom browser executable or a different Puppeteer package, record those details too: Puppeteer’s configuration guide says the standard package downloads and uses a specific Chrome version by default, while puppeteer-core ignores Puppeteer config files and environment variables. The guide opened from the /next/ path is prerelease documentation, so verify the configuration behavior for your installed version.

Wait for readiness, not a guessed timeout

For repeatable screenshots, tie capture to a known page state: for example, a report container appearing, or a computed property taking its expected value. A fixed delay can be useful for a known animation or delayed render, but it can also make the script slower without proving that the stylesheet loaded. Check the result by inspecting a computed style when appearance matters.

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

Reuse the browser when capturing several pages

Launching Chrome for every file adds avoidable setup work. For a batch, launch one browser, create or reuse pages as appropriate, and close the browser in a finally block so it is cleaned up even if navigation or capture throws. Keep per-page waits tied to the content being rendered; do not assume a single wait condition fits every document.

Best Value
Anker USB C Hub, 5-in-1 USBC to HDMI Splitter with 4K Display
  • 5-in-1 Connectivity: Equipped with a 4K HDMI port, a 5 Gbps USB-C data port, two 5 Gbps USB-A ports, and a USB C 100W PD-IN port. Note: The USB C 100W PD-IN port supports only charging and does not support data transfer devices such as headphones or speakers.
  • Powerful Pass-Through Charging: Supports up to 85W pass-through charging so you can power up your laptop while you use the hub. Note: Pass-through charging requires a charger (not included). Note: To achieve full power for iPad, we recommend using a 45W wall charger.
  • Transfer Files in Seconds: Move files to and from your laptop at speeds of up to 5 Gbps via the USB-C and USB-A data ports. Note: The USB C 5Gbps Data port does not support video output.
  • HD Display: Connect to the HDMI port to stream or mirror content to an external monitor in resolutions of up to 4K@30Hz. Note: The USB-C ports do not support video output.
  • What You Get: Anker 332 USB-C Hub (5-in-1), welcome guide, our worry-free 18-month warranty, and friendly customer service.

Check the installed Puppeteer version

The official Puppeteer API pages surfaced as version 25.12.0 on September 29, 2026. That is version-specific documentation, not a guarantee about every installation. If a method, option, or launch behavior differs, inspect the API documentation matching your installed version and note which browser executable Puppeteer is using.

Common questions

Can I pass a local HTML filename directly to page.goto()?

Use an absolute file URL instead of relying on a raw filename. Convert a resolved path with pathToFileURL() so the URL is encoded correctly.

Why does page.setContent() leave my local CSS unapplied?

It assigns the HTML string; it does not navigate to the file that would normally provide the base location for a relative stylesheet link. Include CSS inline or attach the file with addStyleTag().

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

Should I disable Chrome’s web security to load local CSS?

Not as a routine fix. First check the file URL, stylesheet path, failed requests, and actual browser error. Broad security changes can mask the wrong problem and weaken the browser’s protections.

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.