Skip to content

Instantly share code, notes, and snippets.

@philfreo
Last active January 30, 2024 16:20
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save philfreo/44e2e26a65820497db234d0c66ed58ae to your computer and use it in GitHub Desktop.
Save philfreo/44e2e26a65820497db234d0c66ed58ae to your computer and use it in GitHub Desktop.
Three ways to make a PDF from HTML in Python (preferred is weasyprint or phantomjs)
def render_pdf_weasyprint(html):
from weasyprint import HTML
pdf = HTML(string=html.encode('utf-8'))
return pdf.write_pdf()
def render_pdf_xhtml2pdf(html):
"""mimerender helper to render a PDF from HTML using xhtml2pdf.
Usage: http://philfreo.com/blog/render-a-pdf-from-html-using-xhtml2pdf-and-mimerender-in-flask/
"""
from xhtml2pdf import pisa
from cStringIO import StringIO
pdf = StringIO()
pisa.CreatePDF(StringIO(html.encode('utf-8')), pdf)
resp = pdf.getvalue()
pdf.close()
return resp
def render_pdf_phantomjs(html):
"""mimerender helper to render a PDF from HTML using phantomjs."""
# The 'makepdf.js' PhantomJS program takes HTML via stdin and returns PDF binary via stdout
# https://gist.github.com/philfreo/5854629
# Another approach would be to have PhantomJS do a localhost read of the URL, rather than passing html around.
from subprocess import Popen, PIPE, STDOUT
import os
p = Popen(['phantomjs', '%s/pdf.js' % os.path.dirname(os.path.realpath(__file__))], stdout=PIPE, stdin=PIPE, stderr=STDOUT)
return p.communicate(input=html.encode('utf-8'))[0]
// PhantomJS: generate PDF to stdout from HTML in stdin.
// Example: echo "<b>test</b>" | phantomjs makepdf.js > test.pdf && open test.pdf
var page = require('webpage').create(),
fs = require('fs');
page.viewportSize = { width: 600, height: 600 };
page.paperSize = { format: 'Letter', orientation: 'portrait', margin: '1cm' };
page.content = fs.read('/dev/stdin');
window.setTimeout(function() {
page.render('/dev/stdout', { format: 'pdf' });
phantom.exit();
}, 1);
@gokulk16
Copy link

gokulk16 commented May 28, 2018

Any benchmarks of these three methods?. Would be great if you have any performance stats like time taken to print a complex 100-page pdf, memory used, etc

@epogrebnyak
Copy link

if you are on Windows, weasyprint is hard to get going

@panamantis
Copy link

Oh man, xhtml2pdf can't even render an image without dividing the page into "frames". Don't recommend. Likely best to allow the browser to render it ... and find a way to save to pdf.

@FerociousCentaur
Copy link

Can i use any of them to include highcharts (which is in scripts tag) in my pdf and actually make the pdf in background without opening it in any browser.

@philfreo
Copy link
Author

@FerociousCentaur
Copy link

Thank for your quick reply @philfreo.
Export module allows only one charts image or pdf at a time...but i have many charts which need to be included in the same pdf...that is why i was thinking of using a converter like xhtml2pdf which would load my html page and convert it..but turns out that ot doesnt load the javascript the html template

@philfreo
Copy link
Author

I would use a headless browser. Of these options, phantomjs, but I would look into more modern headless browser options since this gist is a few years old.

@antoniogamizbadger
Copy link

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment