Recommended Free Tools
To change a website’s appearance only in a Playwright screenshot, pass CSS through the screenshot’s style option; for a Playwright Test visual assertion, use stylePath. If the change should remain active for later page actions—or you are using Puppeteer—inject a stylesheet with page.addStyleTag(), then capture. The key choice is whether your CSS is temporary capture styling or a change to the page itself.
Choose the right CSS method
| Method | Use it for | Where the CSS applies |
|---|---|---|
Playwright Test stylePath |
Visual regression assertions with toHaveScreenshot() |
During the screenshot assertion; accepts one stylesheet path or an array of paths |
Playwright page.screenshot({ style }) |
A direct Playwright screenshot with a one-off CSS override | For the screenshot operation |
Playwright or Puppeteer page.addStyleTag() |
CSS that should remain in effect for subsequent page steps | Inserted into the document as a style element or linked stylesheet |
Playwright documents stylePath for screenshot assertions, including hiding volatile elements, piercing Shadow DOM, and applying styles to inner frames. It was added in Playwright v1.41; check the documentation for the version installed in your project: Playwright visual comparisons. The direct Page API options are documented at Playwright Page API.
Apply CSS to a Playwright Test screenshot assertion
Use stylePath when your test uses Playwright Test’s toHaveScreenshot() assertion and you want the stylesheet to affect the visual comparison without becoming an application styling change. Save a stylesheet next to your test, then pass its path to the assertion.
Test file
import { test, expect } from '@playwright/test';
import path from 'node:path';
test('page screenshot ignores the changing chat widget', async ({ page }) => {
await page.goto('https://example.com');
await expect(page).toHaveScreenshot({
stylePath: path.join(__dirname, 'screenshot.css'),
});
});
screenshot.css
/* Hide a changing widget that is irrelevant to this visual assertion. */
.live-chat-widget {
visibility: hidden !important;
}
For projects targeting environments where __dirname is unavailable, use the path convention supported by your module system, such as an absolute path derived from import.meta.url. The essential API choice remains stylePath; its value can be a stylesheet file name or an array of file names.
#1 Best Overall
Apply CSS to a direct Playwright screenshot
For a regular screenshot rather than a Test assertion, put stylesheet text in the style option. This is the shortest route for capture-only changes such as hiding a volatile timestamp or chat control.
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.screenshot({
path: 'capture.png',
fullPage: true,
style: '.live-chat-widget { visibility: hidden !important; }',
});
} finally {
await browser.close();
}
The example uses domcontentloaded as a navigation milestone, not a promise that every image, font, or asynchronous component is ready. If the page content you need appears later, wait for a meaningful selector or other page-specific readiness condition before capturing.
Inject CSS into the page with Playwright
Use page.addStyleTag() when later operations should see the altered page state—for example, if you will inspect the page after the screenshot or take several captures with the same styling. The API accepts CSS text through content, as well as path or URL inputs.
Rank #2
- HTML CSS Design and Build Web Sites
- Comes with secure packaging
- It can be a gift option
import { chromium } from 'playwright';
const browser = await chromium.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.addStyleTag({
content: '.live-chat-widget { visibility: hidden !important; }',
});
await page.screenshot({ path: 'capture.png' });
} finally {
await browser.close();
}
To load an existing stylesheet instead, use the supported path or url input to addStyleTag(). Remember that this inserts styling into the live document, unlike screenshot-scoped CSS.
Inject CSS and capture with Puppeteer
Puppeteer does not use Playwright’s screenshot style or Test stylePath options. Insert a style tag into the page, then call the screenshot API:
import puppeteer from 'puppeteer';
const browser = await puppeteer.launch();
const page = await browser.newPage();
try {
await page.goto('https://example.com', { waitUntil: 'networkidle2' });
await page.addStyleTag({
content: '.live-chat-widget { visibility: hidden !important; }',
});
await page.screenshot({ path: 'capture.png', fullPage: true });
} finally {
await browser.close();
}
Puppeteer’s guide demonstrates networkidle2 as one navigation option, but it is not the right readiness rule for every site. A page can keep background requests open, or finish network activity before the particular content you need is rendered. Puppeteer documents addStyleTag() at Page.addStyleTag() and capture methods in its screenshots guide.
Rank #3
Write CSS that stabilizes the image without hiding its meaning
Use a selector that targets only the element you mean to alter. A narrow selector makes it less likely that a site redesign or reused class will hide important content elsewhere. Add !important when page styles otherwise override the masking rule.
- Hide an irrelevant widget:
.live-chat-widget { visibility: hidden !important; }preserves its layout space while making it invisible. - Remove it from layout: use
display: none !important;when the widget’s reserved space also makes the capture inaccurate. This can shift neighboring content, so choose deliberately. - Target only a changing value: mask a timestamp or rotating ad rather than hiding the whole section around it.
- Preserve the content being evaluated: suppress only noise irrelevant to the screenshot, such as transient overlays or a live clock. Do not hide page content that a reviewer needs to see.
Playwright’s screenshot stylesheet is specifically documented as a way to hide dynamic or volatile elements and improve screenshot determinism. The same CSS can still produce different pixels if the underlying browser, operating system, settings, hardware, power source, or headless mode changes. For meaningful visual comparisons, keep the rendering environment consistent; see Playwright’s visual comparison guidance.
Crashes, No Sound, or Screen Glitches?
Random freezes, missing sound and display glitches usually trace back to one bad driver. Find and replace yours safely.Free scan · under a minuteWindows Errors? Fix Them Before They Spread
Repair common Windows errors and clear accumulated junk for a smoother, more stable PC - no reinstall needed.Free scan · no reinstallWait for the right page state before capture
CSS injection changes styling; it does not make a page ready. Navigation completion alone may not mean the key image, web font, client-rendered section, or delayed content has appeared. Identify what must be present and wait for it before capturing:
await page.goto('https://example.com', { waitUntil: 'domcontentloaded' });
await page.locator('main article').waitFor({ state: 'visible' });
await page.screenshot({
path: 'capture.png',
style: '.live-chat-widget { visibility: hidden !important; }',
});
Replace the selector with an element that represents the content you actually need. For pages whose important state is driven by an interaction, perform that interaction and wait for its result before the screenshot. Network-idle waits can be useful on some pages, but they are not universally sufficient or guaranteed to finish on pages with ongoing requests.
Capture a particular element instead of the whole page
If the target is a component rather than the whole document, capture its element after applying the same CSS method described above. Puppeteer supports an element handle’s screenshot method; Playwright offers locator screenshots. This can make the output more focused, but the selected element must be visible and laid out before capture.
// Playwright
await page.locator('.product-card').screenshot({ path: 'product-card.png' });
When using screenshot-scoped CSS, ensure its selector still matches elements inside the region being captured. If you use an injected stylesheet, it remains part of the page for subsequent actions unless you remove or replace it.
Free tools Windows power users keep installed
One-click scans. No signup required.
Best Value
- Includes access code
Troubleshoot CSS screenshot problems
- The target remains visible. Check that the selector matches the live page, including capitalization and state-dependent classes. Inspect the element in the browser or query it with
page.locator('.live-chat-widget').count(). A more specific rule or!importantmay be needed if the site overrides your declaration. - The rule works in a direct capture but not a test assertion. Make sure you are using
stylePathinside Playwright Test’stoHaveScreenshot(), not as an option to an unrelated screenshot method. For a direct Page screenshot, use itsstyleoption. - The page changes after the screenshot. A stylesheet inserted by
addStyleTag()changes document state. If only the image should change, use Playwright’s screenshot-scoped option instead. - Styles do not reach an embedded or shadowed element. Playwright documents screenshot styles as piercing Shadow DOM and applying to inner frames. For a different API or setup, verify the element’s context and whether your selector can reach it; ordinary document CSS may not select into every isolated context.
- Content is missing or still loading. Wait for the specific content or state needed before taking the screenshot. CSS cannot force a late image or client-rendered component to load.
- Visual diffs remain across machines. Match the browser version and rendering environment used for the baseline. CSS does not remove variation caused by operating system, settings, hardware, or headless mode.
- The image has unexpected blank space.
visibility: hiddenleaves the element’s layout footprint. Switch todisplay: noneonly if collapsing that space is appropriate.
Or skip the browser setup
If you need a screenshot from code without managing a browser session, ScreenshotNeo is a website screenshot API and MCP server. Its API accepts one GET request with a URL and returns an image or PDF; custom CSS and JavaScript are among its capture options. API details and the full parameter reference are in the ScreenshotNeo documentation.
curl -G "https://api.screenshotneo.com/v1/shot"
-d access_key=YOUR_API_KEY
--data-urlencode url=https://example.com
--data-urlencode 'css=.live-chat-widget { visibility: hidden !important; }'
-o shot.webp
Use your API key in place of YOUR_API_KEY. The request above demonstrates the API call and CSS parameter; consult the documentation for the current accepted parameter names and response options. ScreenshotNeo removes cookie/consent banners, newsletter popups, and chat widgets before capture; each of those cleanup steps can be turned off. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for Claude, Cursor, and other MCP clients.
The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Start at ScreenshotNeo’s free sign-up.
FAQ
Can I use a CSS file instead of writing CSS in the test?
Yes. For a Playwright Test screenshot assertion, point stylePath at a CSS file; it also accepts an array of stylesheet paths.
The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEScan for outdated or missing drivers - takes under a minuteDriver Scan →Does screenshot CSS change the website for other visitors?
No. These methods apply styling in the browser session used for your capture; they do not edit the site’s deployed source files.
Quick Recap
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.

