HTML markup is text, not an image. To obtain a Base64-encoded JPG, first render the page (or element) in a browser and take a JPEG screenshot, or serialize pixels that already exist in a canvas. A browser screenshot is the correct route for ordinary HTML layouts; canvas.toDataURL() is the efficient route when your application already draws the image on a canvas.
Choose the conversion route
| Source | Method | Result | Use it when |
|---|---|---|---|
| Rendered HTML page or element | Puppeteer screenshot | JPEG bytes or a Base64 string | You need the visual layout, CSS, fonts and images as a browser sees them |
| Pixels already drawn in a canvas | canvas.toDataURL('image/jpeg', quality) |
A JPEG data URL | Your application already has the bitmap in a canvas |
Neither method converts tags directly into JPEG bytes. HTML must be rasterized first. Decide whether the receiving API wants a complete data URL such as data:image/jpeg;base64,... or only the Base64 payload after the comma.
Convert a rendered HTML page with Puppeteer
Install and load the page
Use a current Puppeteer installation (the screenshot options reference was reviewed for version 25.12.0 on September 29, 2026; option names can change between versions).
npm install puppeteer
The following script opens a URL, waits for the network to become idle, captures the complete document as JPEG, and writes both the binary file and a Base64 string.
What’s actually slowing this PC down?
Pick the symptom - the matching free tool is one click away.
#1 Best Overall
- High-gloss, bright white, resin coated photo paper
- Print high quality photos for glass frames and photo albums
- Smudge and water-resistant quick dry surface
- Look and feel of traditional photographs
- 4x6 Borderless, 100 Sheets
const puppeteer = require('puppeteer');
const fs = require('node:fs/promises');
(async () => {
const browser = await puppeteer.launch({ headless: true });
try {
const page = await browser.newPage();
await page.setViewport({ width: 1440, height: 900, deviceScaleFactor: 1 });
await page.goto('https://example.com', {
waitUntil: 'networkidle2',
timeout: 90_000
});
const base64 = await page.screenshot({
type: 'jpeg',
quality: 85,
fullPage: true,
encoding: 'base64'
});
await fs.writeFile('page.jpg', Buffer.from(base64, 'base64'));
await fs.writeFile('page.jpg.b64', base64, 'utf8');
console.log(base64); // raw Base64, without a data-URL prefix
} finally {
await browser.close();
}
})();
type: 'jpeg' is important: otherwise a PNG may be produced. JPEG quality is a number from 0 to 100 and does not apply to PNG. A quality around 80–90 is a practical starting point; lower values reduce size but show more compression artifacts.
Capture only an element
For a card, invoice, chart or other component, select it and call the element screenshot method. The element must be present and visible when captured.
const card = await page.waitForSelector('#invoice', { visible: true });
const base64 = await card.screenshot({
type: 'jpeg',
quality: 90,
encoding: 'base64'
});
This avoids huge full-page images and gives the receiving system only the region it needs. For a precise arbitrary rectangle, use a clip with x, y, width and height coordinates.
Make dynamic pages deterministic
- Wait for a meaningful selector, such as
await page.waitForSelector('.report-ready'), rather than assuming navigation means rendering is complete. - Use
page.evaluateto click tabs, dismiss an application dialog, or apply a test state before the screenshot. - Set viewport dimensions and device scale factor explicitly so line wrapping and pixel dimensions do not vary between runs.
- For lazy-loaded images, scroll through the document or wait for each image’s
completeproperty before capture. - Use
fullPage: truefor the complete document; use an element screenshot when the target is a component.
Authentication can be established with Puppeteer cookies or request headers before navigation. Do not put private tokens in a public client-side page or in a URL that may be logged.
Free tools Windows power users keep installed
One-click scans. No signup required.
Rank #2
- Excellent photo results with vibrant colors.
- Pack of 50 Sheets
Get Base64 from a canvas
When the pixels are already in a canvas, no page screenshot is necessary:
const canvas = document.querySelector('#preview');
const dataUrl = canvas.toDataURL('image/jpeg', 0.85);
const base64 = dataUrl.slice(dataUrl.indexOf(',') + 1);
console.log(dataUrl); // data:image/jpeg;base64,...
console.log(base64); // payload only
The second argument is a JPEG quality value from 0 to 1. The method returns a data URL, not a bare payload. Remove everything through the first comma only when the destination explicitly requests raw Base64.
Canvas limitations
- Canvas serialization exports the bitmap, not the HTML elements layered around it.
- Canvas dimensions determine output dimensions; CSS scaling does not add detail.
- A canvas containing cross-origin images without appropriate CORS permission can become “tainted,” causing export to fail with a security exception.
- JPEG support can vary by browser. PNG is the required baseline format in the HTML specification; test JPEG behavior in every browser you support.
- Transparent pixels are not represented as transparency in JPEG. Use PNG when an alpha channel is required.
Data URL versus raw Base64
Use the complete data URL when assigning an image source:
img.src = dataUrl;
Use the raw value when sending JSON to an API that documents a separate media type:
Do these 3 things before closing this tab:
1Clear out junk files and repair common Windows errors2Fix the driver behind crashes, sound loss and screen glitches3Repair Windows errors before they cause bigger problemsRank #3
- Create affordable photo projects with a bright, glossy finish
- Customize photos with easy-to-use editing tools and print from your phone with HP Smart app
- Handle durable, quick-dry photos right from the printer
- Make memories last with photos that resist fading for decades when printed with Original HP Ink
await fetch('/upload', {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({
filename: 'page.jpg',
content_type: 'image/jpeg',
base64
})
});
Base64 increases the payload compared with binary JPEG, so check request-size limits and prefer multipart binary upload when the API supports it. Decode on the server with the language’s Base64 decoder and validate the decoded bytes as an image rather than trusting a filename or MIME field.
Or skip the browser setup
ScreenshotNeo is a website screenshot API and MCP server. One GET request renders a URL and returns PNG, JPEG, WebP or PDF; you can Base64-encode the returned JPEG bytes in your own application. It removes cookie/consent banners, newsletter popups and chat widgets before capture. Bot checks, blank pages, timeouts, failed loads and cache hits are not billed, and response headers identify the page verdict and billing status.
For developers, its 63 options include full-page lazy-image capture, CSS-selector element capture, dark mode, 12 device presets or custom viewports, retina scale, custom CSS and JavaScript, click-before-capture, selector waits, delay or network-idle waits, ad/tracker/request blocking, headers, cookies, user agent and Authorization, timezone and geolocation, transparent backgrounds, resizing, configurable-TTL caching, signed image links, asynchronous jobs with signed webhooks, bulk capture of up to 100 URLs per call, a usage API and an OpenAPI specification. Existing parameter names used by other screenshot APIs are accepted to ease migration. An MCP server provides take_screenshot, get_page_info and capture_pdf tools for Claude, Cursor and other MCP clients.
Here is the one-call cURL example (see the ScreenshotNeo documentation for authentication and options):
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Repair Windows errors before they cause bigger problemsFix Now →Scan for outdated or missing drivers - takes under a minuteDriver Scan →curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp
Request JPEG instead of WebP with the service’s documented output parameter, then Base64-encode the downloaded bytes in your program. Equivalent starter requests are:
Rank #4
- Reliable quality and large capacity: Made from high-quality 180GSM/48lb paper, with uniform thickness and a smooth surface. Standard letter size (8.5 x 11 inches / 216 x 279 mm), 40 sheets per pack
- Fast Ink Absorption & Smudge-Proof Performance:Features advanced coating technology for ultra-fast ink absorption. It prints without smudging and reduces waiting time. Ensures crisp images right after printing, ideal for high-efficiency office and home use
- Vibrant, True-to-Life Color Reproduction:Optimized for dye ink to deliver rich, vivid colors and accurate color matching. With outstanding color fidelity, it accurately captures every image detail, ensuring precise and vivid presentation of photos, flyers, and other printed materials
- Single-Sided Glossy Finish for Stunning Visuals:Boasts a premium single-sided glossy surface that enhances color vibrancy and image clarity. Ink Absorbent Coating prevents ink penetration and ensures stable stacking, perfect for creating professional-looking prints without bulk.The blank back provides handy space for your notes or explanations
- Versatile Application Scenarios for All Your Needs:Ideal for a wide range of uses, including photo printing, promotional flyers, product brochures, classroom handouts and home crafts (like DIY chip bags). Compatible with most inkjet printers, meeting both professional and personal printing demands
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(`${res.status} ${res.statusText}`);
const bytes = Buffer.from(await res.arrayBuffer());
ScreenshotNeo includes 1,000 shots per month free with no card. Paid plans start at $5 for 3,000 shots; every feature is on every plan, and yearly billing provides two months free. Create a free ScreenshotNeo account to try it.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Troubleshooting
The output is PNG, not JPG
Set type: 'jpeg' in Puppeteer or pass 'image/jpeg' to toDataURL. Verify the response content type and file extension together.
The screenshot is blank or incomplete
Navigation completion is not the same as application readiness. Wait for a content selector, network idle, fonts and images; increase the navigation timeout for slow sites. For lazy content, scroll before capture.
Fonts or layout differ from the visible site
Use the same viewport, device scale factor, timezone and user agent as the target environment. Ensure web fonts finish loading and that the page is not serving a mobile layout at your chosen width.
Best Value
- Photo Paper Package: 36 sheets of glossy photo paper, 8.5×11 inch, industry standard 180gsm/48lb, single-sided printing and blank back side for recording or writing something; compatible with inkjet printers and dye ink
- Glossy Finish: our glossy photo paper features its a reflective finish, that adds a professional and attractive touch and makes every picture look like a work of art; the printed photos and graphics are so outstanding
- Leave Vivid Colors: thanks to the good ink absorption of the picture paper, the printed photos come out vibrant colors and sharp details that truly come to life; remain beautiful landscapes and impressive moments forever
- Instant Dry: due to the advanced super cast coating, the ink on prints dry quickly without smearing and jamming; plus, the prints retain their vibrant color over time; makes your memories and designs shine in their full glory
- Wide Application: perfect for printing photos to record important and sweet moments, and also ideal for printing detailed graphics, various greeting cards, posters, chip bags, flyers, brochures, calendars, baby book
toDataURL throws a security error
One or more canvas images came from another origin without CORS permission. Host the asset on the same origin or configure the asset server to allow the requesting origin before drawing it.
The receiving API rejects the string
Check whether it expects raw Base64 or a data URL. Remove line breaks, preserve padding characters such as =, and ensure your JSON transport has not truncated the value.
The JPG has unexpected black or solid backgrounds
JPEG has no alpha channel. Paint an explicit background color before export, or use PNG when transparency matters.
Windows 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 reinstallCrashes, 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 minuteReliability, performance and cost considerations
- Rendering a browser page costs more CPU and memory than serializing an existing canvas; reuse a Puppeteer browser process for batches rather than launching one per URL.
- Full-page captures consume memory proportional to page dimensions. Element captures and sensible viewport sizes are safer for long documents.
- JPEG quality, dimensions and device scale factor determine output size. Measure decoded dimensions and compressed bytes against the receiving service’s limits.
- Set explicit timeouts, close pages, and record URL, viewport, status and capture duration so failed jobs can be retried.
- Do not treat a successful HTTP response as proof of a useful image: inspect content type, byte length and (where available) a page verdict.
Frequently asked questions
Can I convert an HTML string without hosting it?
Yes. In Puppeteer, call page.setContent(html, { waitUntil: 'networkidle0' }) and then take the JPEG screenshot. External fonts, images and scripts still need reachable URLs or embedded data.
Is Base64 a different image format?
No. Base64 is an encoding of JPEG bytes. The image remains JPEG; Base64 only changes how those bytes are represented for transport.
Should I use PNG instead?
Choose PNG for lossless text, sharp line art or transparency. Choose JPEG for photographic or opaque content where a smaller file is more important than lossless quality.
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.
The Tool Desk
Outbyte PC Repair FREEClear out junk files and repair common Windows errorsFree Scan →Outbyte Driver Updater FREEFix the driver behind crashes, sound loss and screen glitchesFind Drivers →




