Driver FixRecommendedSound, Wi-Fi or graphics acting up? Check drivers firstFind missing or outdated drivers fast.Check DriversOctober DealsAmazon USOctober deal check: compare before you payAmazon US: current deals, useful picks and tech finds.Check DealsPC HealthRecommendedCrashes, freezes, slowdowns? Check your PC nowSpot repairable issues before they interrupt work.Check PC×
Skip to content
html2canvas

How to Fix Blurry Text in jsPDF (Native Text, html2canvas, Fonts, and px Units)

Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Blurry jsPDF text usually has one of two causes: the PDF contains a low-resolution image of the page, or CSS-pixel dimensions are being scaled incorrectly. First determine which output you made. Text added with doc.text() is vector text and should remain crisp and selectable. Output produced through html2canvas, canvas.toDataURL(), addImage(), or addSvgAsImage() is raster content, so its sharpness is limited by the source canvas pixels. Use native jsPDF text whenever the layout permits; if rasterization is required, increase the canvas resolution without enlarging the image beyond its effective print resolution.

1. Identify whether the PDF contains text or an image

Open the PDF in a viewer and try to select a word. If individual characters can be selected and searched, the page contains PDF text. Zooming should keep the letter edges clean. If the entire page selects as one object, or selection is impossible, you exported a bitmap. Zooming a bitmap eventually reveals pixels regardless of the PDF page size.

  • Vector path: doc.text(), setFont(), setFontSize(), and embedded fonts.
  • Raster path: html2canvas, a canvas data URL, addImage(), or an SVG converted to an image.

This distinction determines the fix. No amount of PDF viewer zooming or metadata changes can restore detail that was never present in a raster source.

2. Prefer native jsPDF text

Rebuild headings, labels, table values, and body copy with jsPDF text APIs instead of taking a screenshot of the entire HTML page. Native text is selectable, searchable, generally smaller, and remains sharp at high zoom and print size.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Minimal sharp-text example

import { jsPDF } from 'jspdf';

const doc = new jsPDF({
  unit: 'pt',
  format: 'a4',
  putOnlyUsedFonts: true,
  floatPrecision: 16
});

doc.setFont('helvetica', 'normal');
doc.setFontSize(12);
doc.text('Sharp, selectable PDF text', 72, 72);
doc.save('sharp-text.pdf');

Use points, millimetres, or another deliberate physical unit for the document and calculate positions consistently. Keep the documented defaults for precision, userUnit, and floatPrecision unless measurements show that a change is needed. Repeatedly rounding coordinates in application code can create visible alignment errors, but increasing numeric precision cannot turn an image into vector text.

When native text is not a drop-in replacement

Complex CSS layout, filters, gradients, web fonts, and browser-only line wrapping may not reproduce exactly with jsPDF primitives. In those cases, keep only the genuinely visual parts as images and draw important labels or captions as native text over them. This hybrid approach preserves searchable text while limiting raster content.

3. Correct CSS-pixel units with the px_scaling hotfix

If you construct jsPDF with unit: 'px', enable the documented px_scaling hotfix:

import { jsPDF } from 'jspdf';

const doc = new jsPDF({
  unit: 'px',
  hotfixes: ['px_scaling']
});

The jsPDF HOTFIX documentation explains that, without this option, the internal scaling factor for the px unit was miscalculated, making drawn components larger than intended. The hotfix corrects that calculation; it does not increase raster resolution or make text vector-based.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Check for unit mismatches

  • Do not pass CSS pixel coordinates to a document configured in points or millimetres without converting them.
  • Do not use a canvas pixel width as though it were a physical PDF width unless you have chosen the intended print size.
  • Keep the same unit assumptions for margins, font sizes, image placement, and page breaks.

4. Increase html2canvas resolution when raster output is required

When the design must be captured as a browser-rendered image, raise html2canvas’s scale. The canvas then contains more physical pixels before it is converted to a data URL and inserted into the PDF.

const canvas = await html2canvas(element, {
  scale: Math.max(2, window.devicePixelRatio || 1),
  useCORS: true
});

const image = canvas.toDataURL('image/png');
const pdf = new jsPDF({ unit: 'pt', format: 'a4' });
pdf.addImage(image, 'PNG', 0, 0, 595.28, 841.89);
pdf.save('rasterized-page.pdf');

A scale of 2 is a practical starting point, not a universal guarantee. Choose it from the target page dimensions, expected print resolution, amount of text, browser memory, and the number of pages. A scale of 3 or 4 can improve small type but may cause large canvases, slow rendering, or memory failures. Test the actual longest page rather than assuming the first page represents the whole document.

Calculate an honest display size

A low-resolution canvas enlarged to fill an A4 page will look soft. Keep the displayed physical size proportional to the canvas pixel dimensions and intended output resolution. For text-heavy screenshots, PNG avoids JPEG compression halos and preserves transparent or high-contrast edges. JPEG can be smaller for photographic content but is usually a poor choice for fine black text on a light background.

SVG and canvas caveat

addSvgAsImage and canvas-to-data-URL workflows still create raster output in the PDF. Increasing the source scale can improve the result, as documented in the jsPDF issue discussing this approach, but it does not make the resulting text vector text. If selectable text matters, use native jsPDF text or a PDF workflow that preserves SVG/text objects.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

5. Load a font with the glyphs you actually use

Sharp geometry is not enough if the font is substituted or characters are missing. jsPDF’s README notes that its 14 standard PDF fonts are limited to the ASCII code page. Unicode text requires an integrated font containing the required glyphs.

Embedding workflow

  1. Obtain a suitable TrueType (.ttf) font with licensing that permits embedding.
  2. Use the jsPDF font converter or load the TTF as binary data.
  3. Register it with addFileToVFS() and addFont().
  4. Select the registered family and style with setFont() before drawing text.
  5. Test every language, symbol, emoji, and combining mark your application emits.
// Outline; font data loading is application-specific.
doc.addFileToVFS('MyFont.ttf', fontBinary);
doc.addFont('MyFont.ttf', 'MyFont', 'normal');
doc.setFont('MyFont', 'normal');
doc.text('Unicode: café — 東京', 72, 110);

If glyphs appear as boxes, disappear, or trigger fallback, inspect font coverage before changing image scale. A fallback font can also alter line breaks and make text appear to have the wrong size.

6. Avoid relying on text transforms to repair softness

Non-uniform text transforms are a fragile first-line fix. The project documents text scaling options, and an issue reports a matrix intended to scale text horizontally having no visible effect. Remove the transform, choose an appropriate font size, adjust the layout, or use a font with the desired proportions. Do not assume a transform has been applied merely because the call succeeds.

7. Verify sharpness at useful viewing scales

  1. Inspect at 100% zoom to check normal reading quality.
  2. Inspect at the intended print size; a high-zoom view can exaggerate harmless anti-aliasing.
  3. Try selecting and copying a sentence.
  4. Search for a distinctive word.
  5. Zoom substantially. Vector edges should remain clean; a raster page will eventually show pixels.
  6. Check a page containing the smallest type, not just a cover page.

8. Troubleshooting by symptom

Symptom Likely cause Fix
Entire page is one selectable image html2canvas or canvas data URL Draw text with doc.text(); otherwise increase html2canvas scale and keep the image size honest.
Text is the wrong physical size with unit: 'px' Incorrect pixel scaling Add hotfixes: ['px_scaling'] and audit unit conversions.
Small type looks soft after scaling Insufficient source pixels Increase canvas scale, reduce the placed image size, or switch that text to native PDF text.
Letters are missing or boxes appear Standard font lacks Unicode glyphs Embed a TTF with required coverage and select it with setFont().
JPEG text has halos Lossy compression Use PNG for text-heavy or transparent content.
Changing a transform does nothing Unsupported or ineffective text matrix Remove the transform and change font size, font choice, or layout.
Browser tab crashes on export Canvas is too large Lower scale, split pages, reduce simultaneous canvases, and test memory limits.
Images or web fonts are absent Cross-origin restrictions Serve assets with appropriate CORS headers and use useCORS: true; otherwise raster capture may be incomplete.

9. Performance, file size, and reliability trade-offs

  • Native text: usually the best combination of clarity, searchability, and file size, but requires layout work.
  • Higher raster scale: improves apparent sharpness while increasing canvas memory, encoding time, PDF size, and risk of browser limits.
  • PNG: lossless edges and transparency, often larger for photographs.
  • JPEG: smaller for photos, but compression artifacts are conspicuous around text.
  • Embedded fonts: improve predictable rendering and Unicode coverage, while adding font data to the file.

Measure the generated PDF on representative devices and printers. A setting that looks excellent on a high-density display may still be unnecessarily expensive for a long, multi-page export.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

For automated website captures, ScreenshotNeo returns a PNG, JPEG, WebP, or PDF from one request. It accepts cookie and consent banners like a visitor, then removes more than 60 known consent platforms, newsletter popups, and chat widgets before the capture. Bot checks, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and billing status.

Its 63 options include full-page lazy-image loading, CSS-selector element capture, dark mode, device presets or custom viewports, retina scale, PDF paper and margin controls, custom CSS and JavaScript, clicks, selector waits, network-idle waits, ad/tracker/request blocking, headers, cookies, user agents, authorization, timezone, geolocation, transparent backgrounds, resizing, configurable caching, signed image links, asynchronous jobs with signed webhooks, bulk capture for up to 100 URLs per call, a usage API, and an OpenAPI specification. An MCP server exposes take_screenshot, get_page_info, and capture_pdf to Claude, Cursor, and other MCP clients.

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://stripe.com -o shot.webp

See the ScreenshotNeo documentation for parameters and response details. The same service also works from Python:

import requests
r = requests.get("https://api.screenshotneo.com/v1/shot", params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"}, timeout=90)
open("shot.webp", "wb").write(r.content)

And Node.js:

const q = new URLSearchParams({ access_key: 'YOUR_API_KEY', url: 'https://stripe.com' });
const res = await fetch(`https://api.screenshotneo.com/v1/shot?${q}`);

The Free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000, and every feature is available on every plan. Create a free ScreenshotNeo account to try it.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

10. A practical decision checklist

  • Need selectable, searchable text? Use native jsPDF text and embed a Unicode font when necessary.
  • Must reproduce browser CSS exactly? Rasterize, but increase source scale and control the physical image size.
  • Using CSS pixels? Enable px_scaling.
  • Seeing missing characters? Verify font glyph coverage and embedding.
  • Seeing memory failures? Reduce scale, split pages, or mix native text with smaller raster regions.
  • Unsure what the PDF contains? Test selection, search, 100% viewing, and high zoom before changing settings.

Frequently Asked Questions

Does increasing jsPDF’s font size fix blurry text?

Only when the text is native PDF text. If the page is a bitmap, changing jsPDF font settings does not alter the pixels already rendered into that image.

Can a PDF viewer make a rasterized jsPDF page vector-sharp?

No. A viewer can resample an image, but it cannot recreate character outlines that were not present in the source canvas.

Should I always set html2canvas scale to 4?

No. Higher values increase memory use and export time. Select a scale from the target page size, smallest type, print requirement, and browser limits, then verify the actual output.

Why is text selectable but still visually poor?

Selectable text can still use an unsuitable or substituted font, incorrect font size, poor placement, or a viewer’s rendering at a non-100% zoom. Check font registration, glyph coverage, units, and the intended viewing scale.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Read next

Recommended PC Tool
Recommended PC Tool
Outdated Drivers Are Slowing You DownFree scan - exact matches
Windows Errors? Fix Them Before They SpreadFree repair scan

Two free Windows tools

One Free Minute Could Fix That PC

Before you go - each of these free tools takes about a minute and tackles what quietly slows a Windows PC down.

Special offer. View Outbyte info, uninstall instructions, EULA, and Privacy Policy.