Convert a Webpage to PDF with Repeated Table Headers on Each Page
Use semantic table markup and print CSS to keep column headings visible across PDF pages. Learn the browser steps, layout fixes, and automated capture options.
To repeat table headings when converting a webpage to PDF, put the column labels inside a semantic <thead> and preserve its print display role with display: table-header-group. Then use the browser’s print preview and save to PDF. This is the standard browser-print approach, but the CSS specification says print user agents may repeat table header rows; it does not guarantee identical output in every browser or document layout. Always inspect the PDF before sharing it.
1. Mark up the table with a real header group
A bold first row is not enough. Use <thead> for column headings and <tbody> for the data rows. This gives the table a real header group that print layout can repeat.
<table>
<thead>
<tr>
<th scope="col">Date</th>
<th scope="col">Product</th>
<th scope="col">Quantity</th>
</tr>
</thead>
<tbody>
<tr>
<td>2026-01-12</td>
<td>Notebook</td>
<td>24</td>
</tr>
<!-- Add the remaining data rows here. -->
</tbody>
</table>
For accessibility and predictable structure, keep column labels in <th scope="col"> cells. If the table has multiple header rows, put all rows that should repeat inside the same <thead>.
2. Add print CSS
CSS 2.2 maps HTML <thead> to display: table-header-group. The CSS Print Profile also includes this display role. Add the rule in a print media query, especially if the site’s existing print styles alter table display behavior.
@media print {
thead {
display: table-header-group;
}
/* Optional: avoid splitting an individual row across pages. */
tr {
break-inside: avoid;
}
}
The optional row rule can help keep a row together, but a very tall row may still need to split or create awkward pagination. The core repeated-header rule is the thead display declaration. See the [W3C CSS 2.2 specification](https://www.w3.org/TR/CSS22/css2.pdf) and [W3C CSS Print Profile](https://www.w3.org/TR/css-print/).
3. Preview and save the webpage as a PDF
- Open the page with the table in your browser and wait for the table and its data to finish loading.
- Open the browser’s Print command and inspect the preview, including pages where the table continues.
- Choose the PDF destination or Save to PDF option.
- Check page size, margins, scaling, and whether browser-added headers and footers should be enabled.
- Save the PDF, then open it and verify that headings repeat, text remains legible, and no columns or rows are clipped.
Browser notes
- Firefox: Open print preview and choose Save to PDF as the destination. Mozilla also documents simplified printing. See [Mozilla’s printing guide](https://support.mozilla.org/en-US/kb/how-print-web-pages-firefox).
- Edge: Use Print and review the page selection, margins, scaling, and preview. Browser headers and footers are optional. See [Microsoft’s Edge printing guide](https://support.microsoft.com/en-us/edge/print-in-microsoft-edge).
- Chrome: Use the browser print flow and inspect the preview. Chrome’s print output is affected by paged-media CSS; Chrome 131 added CSS page-margin boxes. Automatic browser headers and footers can be turned off in the print dialog when unwanted. See [Chrome’s print margin documentation](https://developer.chrome.com/blog/print-margins?hl=en).
Menu names and options can change. Follow the labels in the installed browser version and rely on its preview to confirm the result.
4. Fix common pagination problems
| Symptom | Likely cause | What to check |
|---|---|---|
| Header appears only on the first page | The first row is not inside a real <thead>, or print CSS changed the header group’s display behavior. |
Move the heading row into <thead> and add the print rule thead { display: table-header-group; }. |
| Header is missing or table layout breaks in print | Existing print styles may change table elements to block or another display type. | Inspect computed print styles and restore table semantics for table, thead, tbody, and rows as needed. |
| Columns are clipped or unreadable | The table is wider than the printable page, or print scaling is unsuitable. | Try landscape orientation, adjust margins, or change scaling in preview. Confirm the text is still legible after scaling. |
| Rows split in an awkward place | A row is taller than the available page area or the renderer’s pagination choices do not fit the content. | Use break-inside: avoid on rows as a hint, shorten unusually tall cell content, and inspect the affected pages. |
| Some data is absent | The page did not finish loading, or content is loaded only after scrolling or interaction. | Wait for content before printing and check the page itself for lazy-loaded or interactive data. Scroll through the table if needed before opening print preview. |
| Unexpected URL, date, or page title appears | The browser is adding print headers or footers. | Turn off browser headers and footers in print settings if they are not wanted. |
CSS rules are hints interpreted by the print renderer, not a substitute for checking the actual PDF. The CSS specification permits repeating table header rows but does not require every renderer to do so in every circumstance.
5. Choose print settings for the content
- Page size: Select the size expected by the PDF’s readers or printer.
- Orientation: A wide table may fit better in landscape, though smaller scaling can also reduce legibility.
- Margins: Smaller margins provide more table space; ensure content still has room around the page edge.
- Scale: Fit-to-page can prevent clipping but may shrink text. Check several pages in preview.
- Browser headers and footers: Keep them if page URLs and dates help readers; disable them if they conflict with the document.
- Backgrounds: If colored cells convey meaning, check whether the print dialog includes background graphics and verify that the PDF preserves the distinction.
There is no universal best setting: use the preview to balance complete columns, readable text, and usable page space.
6. Automate PDF capture for an application
If this is a one-off document, browser printing is usually the shortest path. For a recurring workflow, make sure the page is fully rendered before generating the PDF and check the output for repeated headers, page breaks, and missing content. Keep the same semantic table markup and print CSS in the page being rendered. The relevant choices include page size, margins, landscape orientation, and page ranges; confirm the selected renderer’s behavior with your actual document.
ScreenshotNeo is a website screenshot API and MCP server from Yorker Media. It can return a PDF as well as PNG, JPEG, or WebP from one GET request. See the ScreenshotNeo site and API documentation for request options, including PDF paper size, margins, landscape, and page ranges.
Or skip the browser setup
Make a single request to capture a page as a PDF:
curl -G "https://api.screenshotneo.com/v1/shot" \
-d access_key=YOUR_API_KEY \
--data-urlencode url=https://example.com \
-d format=pdf \
-o page.pdf
For example, set the PDF paper size, margins, orientation, or page range using the documented request options for your use case. The key must be kept private in server-side code; do not expose it in a public webpage.
Python
import requests
r = requests.get(
"https://api.screenshotneo.com/v1/shot",
params={
"access_key": "YOUR_API_KEY",
"url": "https://example.com",
"format": "pdf",
},
timeout=90,
)
r.raise_for_status()
with open("page.pdf", "wb") as pdf:
pdf.write(r.content)
Node.js
const q = new URLSearchParams({
access_key: 'YOUR_API_KEY',
url: 'https://example.com',
format: 'pdf',
});
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`Screenshot request failed: ${res.status}`);
const pdf = Buffer.from(await res.arrayBuffer());
await import('node:fs/promises').then(fs => fs.writeFile('page.pdf', pdf));
These examples show the request and save the response body. Consult the ScreenshotNeo docs for the exact PDF parameter names and configuration supported by the API.
ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before capture; each of those steps can be turned off. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and the response identifies the page verdict and billing status in headers. Its MCP server provides take_screenshot, get_page_info, and capture_pdf tools for AI agents. The free plan includes 1,000 shots per month with no card; paid plans start at $5 for 3,000 shots. Sign up for 1,000 free screenshots a month, with no card required.
Performance, reliability, and cost
- Browser printing: No screenshot API request is needed for an occasional manual PDF. Reliability depends on the page finishing its loading work and the browser’s print rendering, so inspect the preview and saved file.
- Repeated or automated capture: Account for page load time, large tables, and content that appears after scrolling or interaction. Test the exact page and options used in production rather than assuming print pagination will match a different browser version.
- ScreenshotNeo pricing: Free includes 1,000 shots per month; Starter is $5 for 3,000, Growth $15 for 15,000, Pro $39 for 60,000, Scale $99 for 250,000, and Business $249 for 1,000,000. Yearly billing gives two months free, and every feature is on every plan. Check the site for current plan details before choosing.
- Usage visibility: ScreenshotNeo marks page verdict and billed status in response headers, which helps distinguish a clean capture from a failed or non-billable result.
FAQ
Will every browser repeat a table header automatically?
No. The CSS specification allows print user agents to repeat table header rows; it does not mandate identical behavior in all renderers and layouts. Use a real <thead>, the print display rule, and verify the PDF.
Can I repeat a visually styled row without changing the HTML?
The reliable semantic approach is to put column headings in <thead>. A row that only looks like a header may not receive table header group behavior.
Can I print only selected pages?
Browser print dialogs commonly expose page selection, and automated PDF capture may offer page ranges. Confirm the available control in the browser or API you use.
Why does my wide table look tiny in the PDF?
The renderer may be shrinking the table to fit the printable width. Try landscape orientation or adjust margins and scaling, then check that all columns fit while text remains readable.


