wkhtmltopdf Alternatives for Generating Indian-Language PDFs from Websites
Choose an HTML-to-PDF engine for Indian-language websites by checking JavaScript needs, font coverage, Indic shaping, and output in your deployment environment.
Direct answer: For a website that depends on JavaScript or browser rendering, start by evaluating Playwright with Chromium. For static HTML and print-focused CSS with controlled system fonts, evaluate WeasyPrint. For advanced paginated publishing where documented Indic shaping support matters and commercial software is acceptable, evaluate Prince. None is a guaranteed replacement for your particular languages, fonts, or pages: compare PDFs made from representative content in the same environment you plan to deploy.
This guide covers tool choice, runnable starting points, language and font validation, deployment, and common failure modes. No rendering tests were performed for this article; the recommendations below are candidates to assess, not claims that a tool has passed your site’s test.
1. Choose an engine based on how the page is built
| Candidate | Start here when | Check carefully |
|---|---|---|
| Playwright with Chromium | The page renders through JavaScript, depends on browser behavior, or uses print CSS. | Browser and font versions, readiness timing, page breaks, print colors, headers and footers. |
| WeasyPrint | You can provide static HTML and CSS, want a Python workflow, and can control installed fonts. | CSS support and shaping for every target script in your exact deployment environment. |
| Prince | You need print-oriented publishing and advanced pagination, and its typography and commercial terms fit. | Exact version, fonts, license, deployment model, and output for your required scripts. |
Playwright’s page.pdf() uses print CSS media and exposes options such as paper format, margins, headers and footers, and background printing. WeasyPrint uses fonts available through Pango, embeds fonts in PDFs, and logs a warning when a character is missing from the selected font and fallbacks. Prince documents Indic-specific OpenType substitutions and language-suitable font configuration; its release notes describe Indic2 shaping support for recent fonts including Noto Serif Devanagari and Nirmala. These documented capabilities are reasons to evaluate each candidate, not a guarantee for every language/font combination. Playwright Page API, WeasyPrint API reference, Prince styling documentation, Prince documentation.
2. Prepare a representative language fixture
Do not judge output from an English-only sample or a single short heading. Build a compact, approved HTML fixture from the site’s real content and include each language and script you need to support. Include text that exercises the combinations found in your material:
- Conjuncts and combining vowel signs.
- Language-specific punctuation and numerals.
- Mixed Latin and Indic text, including URLs or product names if they occur.
- Bold, italic, and other styles actually used by the site.
- Long paragraphs, headings, lists, tables, and links that expose wrapping and pagination.
Have a knowledgeable reader check script-specific spelling and shaping. Keep the HTML, CSS, images, data, font files, and engine configuration identical across candidate runs. Test in the target container or operating system and record the engine version, OS/container, and font package versions.
3. Generate a PDF with Playwright and Chromium
Use this path when the website needs browser rendering or JavaScript. Install Playwright and its Chromium browser, then save the following as capture.mjs. It navigates to the requested page, waits for document fonts, and writes a PDF. The script uses a fixed paper size and print background; change these for your output requirements.
import { chromium } from 'playwright';
const url = process.argv[2];
if (!url) throw new Error('Usage: node capture.mjs https://example.com');
const browser = await chromium.launch({ headless: true });
try {
const page = await browser.newPage();
await page.goto(url, { waitUntil: 'networkidle', timeout: 60000 });
await page.evaluate(() => document.fonts.ready);
await page.pdf({
path: 'page.pdf',
format: 'A4',
printBackground: true,
margin: { top: '18mm', right: '16mm', bottom: '18mm', left: '16mm' }
});
} finally {
await browser.close();
}
Install the runtime and browser using the Playwright installation guide. If the site loads content after the initial navigation, wait for a site-specific selector or application-ready condition before generating the PDF. networkidle is not a universal signal that a single-page app has finished rendering; polling, analytics, or long-lived connections can prevent it from occurring. The official API documents PDF format, margins, headers and footers, scale, page ranges, and related options in page.pdf().
4. Generate a PDF with WeasyPrint
WeasyPrint is a reasonable candidate for static HTML and print CSS when you can install and control fonts in the runtime. Save this as render.py:
from weasyprint import HTML
HTML(url='https://example.com').write_pdf('page.pdf')
Run it with Python after installing WeasyPrint and its system dependencies according to the official installation guide. For generated content, use HTML(string=html, base_url=...) so relative images and stylesheets can resolve. Install the exact font files required by the content in the environment and refresh its font cache where the operating system requires that. Review WeasyPrint’s API reference and CSS support documentation for the features your stylesheet uses. Treat missing-glyph warnings as failures to investigate rather than assuming the PDF is correct because it was created.
5. Evaluate Prince for print publishing
Prince is a commercial print-oriented renderer worth evaluating when pagination and documented Indic typography are central requirements. Its documentation describes language-specific font lists and Indic OpenType substitutions; release notes discuss Indic2 shaping support in recent fonts including Noto Serif Devanagari and Nirmala. Confirm that the version you intend to deploy supports the exact fonts and languages you need. Review current license and deployment terms directly with the vendor before choosing it; this guide does not state current pricing or licensing terms.
Use the Prince documentation for its command-line interface, configuration, language and font styling, and PDF output. A basic command-line shape is:
prince https://example.com -o page.pdf
Check the installed version’s own help and documentation before relying on a command-line option in automation. For generated HTML or user-supplied content, also assess security, filesystem access, and network access in your deployment.
6. Validate shaping, layout, and PDF behavior
- Render the same fixture with each candidate. Preserve the exact content, styles, assets, fonts, and runtime settings.
- Inspect at normal reading size and high magnification. Look for missing glyphs, substituted characters, detached marks, malformed conjuncts, clipping, and unexpected line breaks.
- Check pagination. Inspect page breaks, tables, headings, footers, margins, background colors, and content that crosses page boundaries.
- Check text behavior. If your use case needs it, confirm that text remains selectable and searchable and that fonts are embedded in the final PDF.
- Review logs and warnings. Keep missing-glyph and resource-loading messages alongside the output.
- Repeat in the production-like environment. Record engine, browser, OS/container, and font versions so results can be reproduced.
This is a validation plan, not a report of tests already run. Font choice and shaping support are dependencies of correct Indic output; a Unicode-capable input alone does not ensure a correctly shaped PDF.
7. Deployment, reliability, and cost considerations
- JavaScript and runtime: Chromium offers browser rendering but requires deploying a browser and its dependencies. Static HTML may be simpler to render with a print-focused engine. Compare operational footprint in your actual environment.
- Fonts: Bundle or install known font versions and test after image/container updates. A developer workstation can have fonts that are absent from production.
- Readiness: Wait for the content and fonts your page needs. Set navigation timeouts and handle pages that never reach the expected state.
- Isolation: Treat remote pages and supplied HTML as potentially unsafe input. Limit network and filesystem access and run rendering in an appropriately isolated service.
- Cost: Compare engineering effort, runtime resources, maintenance, and any software license only after the candidate passes the language-quality check. Verify current commercial terms directly. No performance benchmark or price comparison is claimed here.
- Reproducibility: Pin runtime and font versions, retain a fixture and expected-output review process, and rerun it when changing browser, OS, or font packages.
The wkhtmltopdf project describes its converter as using Qt WebKit and warns against processing untrusted HTML, advising sanitization and consideration of alternatives such as WeasyPrint or Prince for controlled report generation. That warning is not proof that another renderer is secure for a particular deployment; evaluate isolation and input trust separately. wkhtmltopdf project status and security guidance.
8. Troubleshooting common PDF problems
| Symptom | Likely cause | What to check or change |
|---|---|---|
| Boxes, blank glyphs, or fallback characters | The intended font is absent, does not cover the code points, or is not available to the renderer. | Install the font in the rendering environment, refresh font discovery if needed, inspect warnings, and rerender the fixture. |
| Characters appear but conjuncts or marks look wrong | The chosen font or shaping path does not produce the needed script behavior, or the production runtime differs from the one tested. | Verify font and engine versions; compare another candidate using the same fixture and have a knowledgeable reader review it. |
| Page is blank or missing dynamic sections | PDF generation began before the app populated the content, or navigation failed. | Check navigation errors and logs, wait for an application-specific selector or ready state, and confirm that required resources can load. |
| Web fonts or images disappear | Relative URLs lack a base URL, resources are inaccessible, or the page is printed before fonts finish loading. | Set a base URL for HTML strings, verify resource access, wait for document.fonts.ready in browser rendering, and inspect network logs. |
| Long paragraphs or tables break badly | Print CSS or pagination rules differ from screen layout. | Add and test print styles, break large tables or sections deliberately, and inspect the output at the target paper size. |
| Text cannot be searched or selected | The PDF may contain rasterized output, or font/text encoding behavior may not meet the requirement. | Check the renderer’s output and font embedding; verify text extraction with the tools used by your workflow. |
| Job hangs or exceeds its timeout | A page has polling or persistent network activity, or a resource never completes. | Use a more specific readiness condition, set bounded navigation and job timeouts, and log failed requests. |
9. Or skip the browser setup
If the goal is a clean screenshot or PDF of a website rather than owning a browser-rendering service, ScreenshotNeo provides a website screenshot API and MCP server. Its one-call API can return an image or PDF; use its PDF options when generating a PDF. Follow the API documentation for output format and PDF parameters.
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)
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}`);
- Cookie banners are accepted and removed before capture; known consent platforms, newsletter popups, and chat widgets are removed. Each step can be turned off.
- Bot checks, blank pages, timeouts, failed loads, and cache hits cost nothing; response headers say the page verdict and whether it was billed.
- An MCP server gives AI agents tools to take screenshots, get page information, and capture PDFs.
- The free plan includes 1,000 screenshots a 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 required.
10. Frequently asked questions
How do I generate a Hindi PDF from a website?
Choose a renderer based on whether the site needs browser JavaScript, then test the actual Hindi text and fonts in the deployment environment. The same approach applies to other Indian languages, with a fixture that covers their specific scripts and content.
Which HTML-to-PDF tool supports Indian languages?
Playwright/Chromium, WeasyPrint, and Prince are candidates with different rendering and typography approaches. Documentation alone cannot establish that a particular language, font, and deployment combination will render correctly; inspect representative output.
Can I keep using wkhtmltopdf?
That depends on your requirements and input trust. The project warns against using it with untrusted HTML. If evaluating another engine, compare output and security controls before switching.
Does a successful PDF command prove the language rendered correctly?
No. A file can be generated while glyphs are missing or shaping is wrong. Inspect the PDF and, where relevant, check searchable text and font embedding.


