The Tool Desk
Outbyte PC Repair FREERepair Windows errors before they cause bigger problemsFix Now →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →Use a print-oriented HTML template, render records in a worker, and control page parity explicitly. For each batch, validate the input, escape every value, render one record (front and back) into HTML, start each new record on the required odd or even page, write to a temporary PDF, then validate page count and record boundaries before publishing the file.
Dompdf, mPDF and TCPDF can all work, but they are not browser engines. Design for the CSS subset your selected library supports, isolate renderer instances, embed deterministic fonts and assets, and test with the exact PHP version and printer settings you will use.
The duplex-safe generation pipeline
- Load and validate rows. Reject missing IDs, malformed dates, unsupported characters or oversized fields before rendering.
- Render one logical record. Escape data and use local, deterministic images and fonts. Keep front and back sides self-contained.
- Apply print geometry. Set paper size, margins, bleed-safe areas and explicit page-break rules in CSS.
- Control parity. Track which physical page the next record must start on. Insert a conditional blank page when the previous record ends on the wrong side.
- Write atomically. Render to a temporary file, validate it, then rename it to the final path.
- Log reproducibility data. Store input IDs, template revision, PHP and renderer versions, page count and validation status.
Define the record contract
Decide whether one record is exactly two pages or may expand. If it must be two pages, make the front and back explicit elements and prevent content from flowing between them. If a record can legitimately use more pages, define whether the next record starts on an odd page, an even page or simply the next available page.
Choosing a PHP renderer
| Library | Layout and CSS | Duplex and pagination controls | Operational notes |
|---|---|---|---|
| Dompdf | Mostly CSS 2.1, with selected CSS3 features such as @import, @media and @page. |
Use explicit page-break rules and test every boundary; browser-only layout features are unsafe assumptions. | The project warns that one Dompdf instance should not render more than one HTML document because parsing and rendering artifacts can persist. Create a fresh instance per document or isolated batch unit. |
| mPDF | Generates PDFs from UTF-8 HTML and supports headers, footers, page numbering, tables of contents and barcodes. Its manual warns that it is dated and may require a template tailored to mPDF. | Conditional AddPage('E') or AddPage('O') inserts a page only when needed to make the current page match the requested parity. |
Convenient for print metadata and duplex rules, but measure memory on your own templates and fonts. |
| TCPDF / tc-lib-pdf | Renders a documented HTML/CSS subset without a browser engine. | addHTMLCell() handles automatic page and region breaks; getHTMLCell() returns operators for caller-controlled placement. Features include page-break controls, orphans, widows and print media. |
More manual placement may be needed when browser-like CSS is important. |
None of these choices has a universally valid throughput or memory number. Measure with your PHP version, template, fonts, image sizes, record count and hardware; do not copy a benchmark from a different workload.
#1 Best Overall
- BEST FOR SMALL BUSINESSES – Engineered for extraordinary productivity, the Brother DCP-L2640DW Monochrome (Black & White) 3-in-1 combines laser printer, scanner, copier in one compact footprint and delivers high-quality black & white prints
- FAST PRINTER WITH EFFICIENT SCANNING – Produces documents quickly with print speeds up to 36 ppm(2) and scan speeds up to 23.6/7.9 ipm(3) (black/color). A 50-page auto document feeder(4) allows for convenient, time saving multi-page scanning and copying
- FLEXIBLE CONNECTION OPTIONS – Easily navigate the changing demands of your business with secure multi-device connectivity via built-in dual-band wireless (2.4GHz / 5GHz) and Ethernet. Or connect locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Print, scan, and manage your wireless printer anytime, from almost anywhere from your mobile device. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(5)
- CHOOSE BROTHER GENUINE TONER – When it’s time to replace your toner, be sure to choose Brother Genuine TN830 or TN830XL replacement toner. And with Refresh EZ Print Subscription Service, you’ll never worry about running out of toner again and you’ll enjoy savings of up to 50%(6) on Brother Genuine Toner. Get started with Refresh today with a Free Trial(1)
Design an HTML template for printing
Use explicit sides and supported CSS
Keep each side in a block with a known height. Avoid JavaScript, flexbox, grid, sticky positioning and generated content unless your chosen renderer documents support for them. Reserve space for headers, footers, barcodes and printer margins.
<style>
@page { size: A4; margin: 12mm 12mm 14mm 12mm; }
html, body { margin: 0; padding: 0; }
.side { min-height: 270mm; page-break-after: always; position: relative; }
.side:last-child { page-break-after: auto; }
.safe-area { padding: 4mm; }
.page-number { position: absolute; bottom: 0; right: 0; }
</style>
<section class='side front'>
<div class='safe-area'>Front artwork and fields</div>
</section>
<section class='side back'>
<div class='safe-area'>Back artwork and fields</div>
</section>
Make duplex alignment deliberate
For short-edge or long-edge binding, front and back artwork may need different horizontal placement or mirroring. Do not assume the PDF viewer’s duplex option will correct artwork registration. Print a one-record test on the target stock, mark the top edge, and verify that the back-side coordinate system matches the printer’s binding edge.
Fonts, images and Unicode
Embed the exact font files required for the job and use stable local paths. Test accented characters, right-to-left text, barcodes and high-resolution images at final paper size. A browser preview is not proof that the PDF engine will shape or embed the same glyphs.
Complete PHP batch example with mPDF
The following worker creates one isolated mPDF instance for a bounded batch. It starts every record after the first on an odd page, so each front side begins on the intended face. Change 'O' to 'E' when your production rule requires an even starting page, and verify the result with a fixture.
Free tools Windows power users keep installed
One-click scans. No signup required.
<?php
declare(strict_types=1);
require __DIR__ . '/vendor/autoload.php';
use MpdfMpdf;
use MpdfOutputDestination;
function esc(mixed $value): string {
return htmlspecialchars((string) $value, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8');
}
function renderRecord(array $row): string {
$id = esc($row['id']);
$name = esc($row['name']);
$address = nl2br(esc($row['address']), false);
$code = esc($row['code']);
return "<style>
@page { size: A4; margin: 12mm 12mm 14mm 12mm; }
.side { min-height: 270mm; page-break-after: always; position: relative; }
.side:last-child { page-break-after: auto; }
.safe { padding: 4mm; }
.id { position: absolute; bottom: 0; left: 0; font-size: 8pt; }
</style>
<section class='side'>
<div class='safe'>
<h1>Membership card</h1>
<p><strong>{$name}</strong></p>
<p>{$address}</p>
<p>Code: {$code}</p>
<span class='id'>Record {$id} — front</span>
</div>
</section>
<section class='side'>
<div class='safe'>
<h2>Terms and contact</h2>
<p>Keep this side aligned to the binding edge selected for your printer.</p>
<span class='id'>Record {$id} — back</span>
</div>
</section>";
}
$rows = json_decode(
file_get_contents(__DIR__ . '/records.json'),
true,
512,
JSON_THROW_ON_ERROR
);
if (!is_array($rows) || $rows === []) {
throw new RuntimeException('No records supplied');
}
$mpdf = new Mpdf([
'format' => 'A4',
'margin_left' => 12,
'margin_right' => 12,
'margin_top' => 12,
'margin_bottom' => 14,
'tempDir' => __DIR__ . '/tmp/mpdf'
]);
$mpdf->SetTitle('Duplex batch');
foreach ($rows as $index => $row) {
foreach (['id', 'name', 'address', 'code'] as $required) {
if (!array_key_exists($required, $row) || trim((string) $row[$required]) === '') {
throw new InvalidArgumentException("Missing {$required} in row {$index}");
}
}
if ($index > 0) {
// Conditional break: add a page only if needed for an odd start.
$mpdf->AddPage('O');
}
$mpdf->WriteHTML(renderRecord($row));
}
$outDir = __DIR__ . '/out';
if (!is_dir($outDir) && !mkdir($outDir, 0775, true) && !is_dir($outDir)) {
throw new RuntimeException('Cannot create output directory');
}
$tmp = tempnam($outDir, 'duplex-');
$final = $outDir . '/cards.pdf';
$mpdf->Output($tmp, Destination::FILE);
if (!is_file($tmp) || filesize($tmp) === 0) {
@unlink($tmp);
throw new RuntimeException('Renderer produced an empty file');
}
if (!rename($tmp, $final)) {
@unlink($tmp);
throw new RuntimeException('Atomic rename failed');
}
echo "Wrote {$final}n";
Install mPDF in the same deployment as the worker and make the temporary directory writable. The example escapes all record fields, uses a fixed page box, and writes atomically; adapt the template to the CSS subset your version supports.
Rank #2
- BEST FOR HOMES & HOME OFFICES – Engineered for consistent, premium print quality, the Brother HL-L2405W Monochrome (Black & White) Laser Printer delivers sharp, crisp prints at an affordable price. Prints one-sided documents at speeds up to 30ppm(2)
- COMPACT, CONNECTED PRINTER – Flexible connection options make this an ideal printer for home use and at-home offices. Securely connect to multiple devices with built-in dual-band wireless (2.4GHz/5GHz) or locally to a single computer via USB interface
- BROTHER MOBILE CONNECT APP – Manage your printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Enjoy seamless, reliable everyday printing with the 250-sheet paper tray(4) and a manual feed slot that enables printing on envelopes and specialty pape
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
Parity, page breaks and blank pages
Choose the required starting face
For a front side that must begin on an odd page, call the renderer’s odd conditional break before each record after the first. For an even start, use the even variant. A conditional break may add no page when parity already matches, which is why it is preferable to blindly inserting a blank page.
When a record overflows
An unexpected third page changes the parity of every later record. Treat overflow as a validation failure when the contract is exactly two pages. Find the offending field, image or font metric, then adjust the template or reject the row; do not silently accept shifted backs.
Independent documents versus one batch
Dompdf explicitly advises against reusing one instance for multiple HTML documents. For Dompdf, create a new instance for each PDF or isolated batch unit. With any engine, bounded batches limit memory growth and make retries cheaper than rerendering an unbounded job.
Recommended Free Tools
Validate before release
- Confirm the file opens and has a non-zero size.
- Count pages and compare with the expected two-pages-per-record total plus any intentional parity blanks.
- Check that every record starts on its required odd or even page.
- Verify no record crosses a forced boundary unexpectedly.
- Print a fixture and confirm front/back registration, orientation and binding edge.
- Check fonts, images, barcodes and Unicode text in the actual PDF.
For a simple automated smoke check on Linux, install the pdfinfo utility and inspect the rendered file:
Rank #3
- FAST PRINT SPEEDS: Print up to 19 pages per minute.
- COMPACT DESIGN: Space-saving, compact design fits anywhere in your home, school or small office.
- WIRELESS CONNECTIVITY: Print from almost anywhere in your workspace using your compatible mobile device.
- PAPER CAPACITY: Up to 150 sheets.
- SUSTAINABILITY: Uses less than 2 watts in Energy Saver mode.
pages=$(pdfinfo out/cards.pdf | awk '/^Pages:/ {print $2}')
[ "$pages" -ge "$(( ${#rows[@]} * 2 ))" ] || exit 1
Use a deterministic fixture with known IDs and boundary markers. Re-run it after changing PHP, the renderer, fonts, images or the template. Keep parity decisions and intentional blank pages in the job log so an operator can explain every page.
Scaling and reliability practices
Chunk work and retry safely
Queue bounded batches rather than one process for millions of rows. Give each job an idempotent input range, write to a unique temporary filename, and rename only after validation. A failed batch can then be retried without replacing a verified file.
Control memory and assets
Large raster images and embedded fonts dominate memory. Resize images to their print resolution, reuse local assets, and avoid loading remote URLs whose content can change between retries. Measure peak memory under production-sized batches; no general library number predicts your workload.
Do these 3 things before closing this tab:
1Repair Windows errors before they cause bigger problems2Scan for outdated or missing drivers - takes under a minute3Clear out junk files and repair common Windows errorsSecurity
Escape text and attributes, allow-list image and font paths, and never pass user-controlled HTML to a renderer with unrestricted filesystem or network access. Strip unexpected CSS that could read local files or trigger remote requests in your deployment model.
Rank #4
- BEST FOR HOME OFFICES & SMALL TEAMS – Engineered for consistent, premium print quality, the Brother HL-L2460DW Monochrome (Black & White) Laser Printer produces documents that are clear, crisp, and easy to review and share, all at an affordable price
- COMPACT, CONNECTED, EXCEPTIONALLY EFFICIENT– Connect with built-in dual-band wireless (2.4GHz/5GHz), Ethernet, or to a single computer via USB interface. Prints at speeds up to 36ppm(2), plus automatic duplex printing saves time and reduces paper waste
- BROTHER MOBILE CONNECT APP – Manage your wireless printer remotely and print from your mobile device anytime, from almost anywhere. Order Brother Genuine Supplies, track toner usage, and complete more work on-the-go(3)
- VERSATILE PAPER HANDLING – Tackle high-volume black & white printing with the 250-sheet capacity paper tray.(4) The manual feed slot enables printing on envelopes and specialty paper
- BROTHER IS AT YOUR SIDE – Backed by Brother with a 1-year limited warranty and free online, call, or live chat support for the life of your printer
Common failures and fixes
Back sides drift to the wrong sheet
Cause: a record overflowed, or parity was inferred from a page count that did not include a conditional blank. Fix: enforce a two-page record contract, use conditional odd/even breaks, and inspect the first failing record in a deterministic fixture.
Content is clipped at the bottom
Cause: the side is taller than the printable area after margins, headers or font substitution. Fix: reduce content, reserve space explicitly, embed the intended font and check the renderer’s page box.
CSS looks correct in Chrome but not in the PDF
Cause: the PHP engine supports a narrower HTML/CSS subset and does not execute browser JavaScript. Fix: replace unsupported layout with block/table structures documented for your engine and move data-dependent work into PHP.
Quick wins for a faster PC:
Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Repeated records render incorrectly
Cause: a renderer instance retained parsing or layout state. Fix: create a fresh Dompdf instance per document or isolate each batch, and avoid sharing mutable renderer configuration between jobs.
Best Value
- FROM AMERICA'S MOST TRUSTED PRINTER BRAND – Perfect for small teams printing professional-quality black & white documents and reports. Perfect for 1-3 people
- WORLD'S SMALLEST LASER IN ITS CLASS – Precision laser printing that fits anywhere
- FAST PRINT SPEEDS – Up to 21 black-and-white pages per minute single-sided
- WIRELESS WITH SELF-RESET – Helps you stay connected
- PRINT FROM ANY DEVICE – Wireless printing from any mobile device, PC or tablet. Works with Microsoft, Mac, AirPrint, Android, Chromebook and more
Missing glyphs, barcodes or images
Cause: the asset path is unavailable to the worker, the font is not embedded, or the barcode/image resolution is insufficient. Fix: use local deterministic paths, register the exact fonts, verify file permissions and inspect the generated PDF rather than only the HTML.
Or skip the browser setup
If your source is already a reachable URL and you need a clean visual capture or PDF without maintaining a headless-browser stack, ScreenshotNeo provides a single HTTP endpoint. It accepts cookie and consent banners like a visitor, removes more than 60 known consent platforms plus newsletter popups and chat widgets before capture, and lets you turn each cleanup step off. Bot checks, CAPTCHAs, blank pages, timeouts, failed loads and cache hits are not billed; response headers report the page verdict and whether the request was billed.
Read the parameter reference in the ScreenshotNeo documentation. This cURL call captures a preview URL as WebP:
curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://example.com/preview -o shot.webp
Equivalent Python:
import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://example.com/preview"}, timeout=90)
r.raise_for_status()
open("shot.webp", "wb").write(r.content)
Equivalent Node.js:
const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://example.com/preview' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);
if (!res.ok) throw new Error(`${res.status} ${await res.text()}`);
require('fs').writeFileSync('shot.webp', Buffer.from(await res.arrayBuffer()));
ScreenshotNeo also offers full-page and element capture, device and viewport controls, retina scale, PDF output with paper size, margins, landscape and page ranges, custom CSS and JavaScript, waits, request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, selectable caching TTLs, signed links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Its MCP server exposes take_screenshot, get_page_info and capture_pdf to Claude, Cursor and other MCP clients.
The Free plan includes 1,000 shots per month with no card. Paid plans start at $5 for 3,000 shots; every feature is included on every plan, and yearly billing gives two months free. Create a free ScreenshotNeo account to try it without a card.
Frequently Asked Questions
How do I test parity without printing an entire batch?
Use a deterministic fixture containing one-, two- and overflow-prone records, then inspect page numbers and boundary markers in the PDF before running a full job.
Should front and back artwork use the same CSS coordinates?
Only if your printer’s duplex and binding settings preserve that coordinate system. Confirm with a marked test sheet; some short-edge and long-edge workflows require mirrored placement.
What should be stored for auditability?
Keep the input range or IDs, template revision, PHP and renderer versions, font revisions, page count, parity decisions and validation result alongside the output filename.
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.




