How to Capture a Website Screenshot with a Fixed Header Included Only Once
Capture a full-page screenshot without repeating a fixed header. Use Playwright to apply a temporary CSS override, then check the layout.
To capture a full-page screenshot with a fixed header appearing only once, use Playwright’s full-page screenshot option and temporarily change the site’s header positioning during capture. Replace .site-header below with the page’s actual header selector, then inspect the result: changing a fixed header to static can alter spacing or move content.
For a page you capture manually, Firefox Developer Tools also supports full-page screenshots. Its documentation describes how to take the screenshot, but does not promise that fixed elements will be removed from repeated capture segments. Check the image afterward.
1. Why a fixed header can repeat
A fixed element stays attached to the viewport as the document scrolls. A sticky element behaves like a relatively positioned element until it reaches its scroll threshold, then sticks within its containing scroll area. If a full-page capture is assembled from multiple viewport images, a pinned header can appear in more than one segment. Browser implementations differ, so this is an explanation of a possible cause, not a guarantee about how a particular browser captures pages.
Playwright describes fullPage as capturing the full scrollable page; its API does not specify a particular stitching algorithm. The CSS behavior of fixed and sticky is described in the MDN position reference.
2. Playwright: capture the page with the header once
This Node.js example starts a browser, opens a page, applies a temporary screenshot stylesheet, and saves a full-page PNG. The stylesheet is applied for the screenshot; it does not change the site’s deployed CSS.
Install
npm init -y
npm install playwright
npx playwright install chromium
Save as screenshot.mjs
import { chromium } from 'playwright';
const targetUrl = process.argv[2] ?? 'https://example.com';
const headerSelector = process.env.HEADER_SELECTOR ?? '.site-header';
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage({ viewport: { width: 1440, height: 900 } });
await page.goto(targetUrl, { waitUntil: 'networkidle', timeout: 60_000 });
await page.screenshot({
path: 'page.png',
fullPage: true,
style: `${headerSelector} { position: static !important; }`,
});
} finally {
await browser.close();
}
Run it with the target URL and your inspected selector:
HEADER_SELECTOR='#main-header' node screenshot.mjs https://example.com
The style option and fullPage are documented in the Playwright Page API. For setup and related screenshot examples, see Playwright Screenshots.
Choose the right CSS override
- Fixed header: Start with
position: static !important. A fixed element is normally outside document flow, so making it static can insert it into the flow and shift the page. If that happens, preserve or compensate for the site’s intended top spacing with a page-specific screenshot stylesheet. - Sticky header: It usually remains in normal flow before it sticks. Resetting it to static may work, but inspect the full result because the containing layout and sticky threshold affect its behavior.
- Multiple headers: Target the one that repeats. Avoid a broad
headerrule if the page has a second header, a table header, or nested sections that should keep their styles. - Selector uncertainty: Inspect the page’s DOM in browser developer tools. A stable ID or specific class is generally a better target than a generic element name.
If the override removes the header but leaves a gap, or pulls content up too far, adjust the temporary CSS to preserve the intended space. There is no universal spacing rule: the right fix depends on how that page lays out its header and content.
3. Pick the capture scope you actually need
| Need | Method | What to check |
|---|---|---|
| Entire page, header once | Playwright fullPage: true plus a targeted screenshot-time style |
Header selector, changed spacing, missing or overlapping content |
| Only the header or another section | Element screenshot | The selected element’s dimensions and whether it is visible |
| Only what is visible now | Ordinary viewport screenshot | Below-the-fold content is intentionally excluded |
| Manual browser capture | Firefox Developer Tools full-page screenshot | Whether the fixed header repeats in the saved image |
Playwright supports screenshots of a locator as well as full-page page screenshots. Firefox documents full-page capture, element screenshots in the Inspector, and the Web Console :screenshot --fullpage helper. Use an element screenshot when the deliverable is just one component, rather than a whole page.
4. Firefox Developer Tools: capture manually
- Open the page in Firefox and open Developer Tools.
- Use the Developer Tools screenshot control to capture the full page, or enter
:screenshot --fullpagein the Web Console. - Open the resulting image and check whether the fixed header appears more than once. Firefox’s documented workflow establishes how to capture the page; it does not state that fixed elements are automatically suppressed.
- If you only need the header element, use the Inspector’s “Screenshot Node” command instead of a full-page capture.
See Mozilla’s Taking screenshots documentation for the manual capture options.
5. Troubleshooting
| Symptom | Likely cause | What to try |
|---|---|---|
| The header still appears more than once | The selector does not match the repeating element, another header is also pinned, or the capture method handles full-page rendering differently. | Inspect the repeated region in the DOM, use its specific selector, and capture again. Check the output rather than assuming all browsers handle fixed elements alike. |
| The header disappears but content starts too high | Changing a fixed element to static changes the document flow or removes the space normally reserved for it. | Add a page-specific spacing adjustment to the screenshot stylesheet and inspect the top of the page. |
| Content overlaps the header | The page uses positioning or offsets that depend on the original fixed or sticky behavior. | Adjust the temporary CSS for that layout. Consider hiding the header only if the header itself is not required in the capture. |
| The rule changes the wrong element | A broad selector matches multiple headers or nested elements. | Use a more specific selector, such as the site header’s ID or unique class. |
| Navigation or images are missing | The page may not have finished loading, or the site may load content as the page scrolls. | Wait for the content you need before capture. If it is lazy-loaded, scroll through the page first and then capture; verify the final image. |
Timeout 60000ms exceeded |
networkidle did not occur before the timeout, which can happen on pages with ongoing network activity. |
Use a suitable readiness condition for the site, such as waiting for a key selector, then capture. Do not treat a timeout as proof the page is ready. |
| Browser executable is missing | Playwright’s browser binary has not been installed in the environment. | Run npx playwright install chromium after installing the package. |
6. Performance, reliability, and cost
A full-page image contains more pixels than a viewport screenshot, so taller pages generally take longer to capture and produce larger files. Keep the viewport and output format appropriate for the image’s use, and avoid capturing content you do not need. The example uses PNG for a lossless output; choose another format only if your capture workflow and downstream use support it.
For repeatable captures, use a consistent viewport, wait for the content that matters, and keep the temporary CSS specific to the target page. Sites with animation, personalized content, consent overlays, or asynchronous loading may produce different images between runs. Inspect representative outputs when changing selectors or page readiness behavior.
The Playwright approach uses your own browser automation environment; its compute and browser costs depend on where and how you run it. The browser documentation does not provide a universal runtime or cost benchmark for this task.
7. Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. A single GET request captures a URL as an image or PDF. This example saves the response body; see the ScreenshotNeo documentation for supported parameters and response details.
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
timeout=90,
)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
await Bun.write('shot.webp', res);
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; each cleanup step can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers report the page verdict and billing status. Its MCP server offers take_screenshot, get_page_info, and capture_pdf for AI agents. The free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000 screenshots. Sign up for 1,000 free screenshots a month, with no card.
8. FAQ
Does setting a fixed header to static always keep it at the top?
No. The result depends on the page’s layout and styles. Inspect the screenshot and adjust the temporary CSS if the header moves or changes the content spacing.
Can I capture only the header?
Yes. Use an element screenshot in Playwright or Firefox’s Inspector screenshot command. That captures the selected element rather than the full page.
Will Firefox automatically remove repeated fixed headers?
The cited Firefox documentation explains full-page and element capture, but does not document automatic suppression of repeated fixed elements. Check the saved image.
Does this change the website for other visitors?
No. Playwright’s screenshot-time style option applies the CSS for the capture, rather than changing the site’s deployed stylesheet.


