Most of us hit this at some point:
“I need to generate a PDF from HTML… and it has to look exactly like the page.”
So you pick a CLI tool or library, wire it up, and it kind of works…
until you have:
- heavy JavaScript
- charts and dashboards in iframes
- React / SPA pages that render mostly on the client
- and a production server that now runs some fragile, homegrown setup
I’ve been through this a few times, so I ended up building a service I wish I had earlier:
a hosted HTML to PDF/PNG API called GoPDFGenie.
This post is about:
- why I built it,
- how the async API works (jobs),
- a simple curl/pseudocode example,
- and how you can run it hosted or self-hosted.
The pain with “just use a PDF library”
Tools like wkhtmltopdf and many HTML to PDF wrappers are fine when:
- the HTML is simple,
- there’s almost no JS,
- and you don’t care too much about pixel-perfect layout.
In real products I kept seeing:
- PDFs that didn’t match the live UI
- things breaking when the frontend team changed layout or added JS
- weird layout quirks in some HTML engines
- and the ongoing cost of maintaining your own conversion infrastructure
Once SPAs, dashboards, and iframes show up, the “just install X and call it a day” story falls apart.
What I wanted instead
For my own projects, I wanted a service that:
- Has a conversion engine tuned for modern web apps
- Handles SPAs, iframes, dashboards, charts
- Is hosted, so I don’t maintain conversion infra again
- Has simple, usage-based pricing
- Still allows self-hosting/on-prem if a team needs that
So I built GoPDFGenie.
👉 Live site: https://gopdfgenie.com
👉 API docs (Swagger UI): https://gopdfgenie.com/swagger-ui/index.html
👉 GitHub examples: https://github.com/gopdfgenie/html-to-pdf-api
Real-world pages I tested it on
When I started building this, I didn’t just test on tidy demo pages.
I tried it on real, messy, modern sites like:
- public charting pages on TradingView (
https://www.tradingview.com) - long, responsive templates like Story and Solid State from HTML5 UP
(
https://html5up.net/story,https://html5up.net/solid-state) - interactive chart galleries like Datawrapper’s scatter plot examples
(
https://academy.datawrapper.de/article/414-examples-of-datawrapper-scatter-plots-time)
In my own testing, a lot of the online HTML to PDF tools I tried — including several that show up right at the top when you search for “html to pdf” — would:
- fail to finish the conversion,
- return an error or blank page, or
- produce PDFs where key parts of the page (charts, iframes, long sections) were missing or cut off.
That experience is a big part of why I built GoPDFGenie and tuned it specifically for JS-heavy, layout-rich pages, so you can feed it “real” URLs instead of only perfectly controlled internal templates.
What GoPDFGenie does (and how the async API works)
At a high level, GoPDFGenie is:
“Give me a URL or HTML, I’ll run it through a modern HTML-to-document pipeline, and you fetch the PDF/PNG when it’s ready.”
The API is asynchronous:
- You create a conversion job.
- The API returns a
jobId. - You poll the job status.
- When it’s
COMPLETED, you fetch the result file as PDF or PNG.
Base URL:
https://gopdfgenie.com/api/v1
Main endpoints:
-
POST /convert/url/async— create a job from a public URL -
POST /convert/async— create a job by uploading HTML/ZIP viamultipart/form-data -
GET /jobs/{jobId}/status— check job status -
GET /jobs/{jobId}/result— download the finished PDF/PNG
Every request uses bearer auth:
Authorization: Bearer YOUR_API_KEY
Hosted SaaS and self-hosted option
By default GoPDFGenie is a hosted HTML to PDF API SaaS:
- Sign up on the site
- Get an API key
- Call
https://gopdfgenie.com/api/v1/... - Pay via a credit-based model (Free, Starter, Pro, Business; credits are based on output size)
For teams that must keep everything in their own environment (compliance, data residency, locked-down networks), I also offer a self-hosted / on-prem license:
- Same core conversion engine
- You run it inside your own infra (containers/VMs, etc.)
- Direct contract for licensing & support
If that’s interesting, there’s an Enterprise section + contact form on the pricing page.
Pseudocode: full async flow
apiKey = "YOUR_API_KEY"
apiBase = "https://gopdfgenie.com/api/v1"
# 1) Submit a URL conversion job
response = HTTP_POST(
url = apiBase + "/convert/url/async?orientation=portrait&outputFormat=pdf&pageSize=A4&quality=STANDARD",
headers = {
"Authorization": "Bearer " + apiKey,
"Content-Type": "application/json"
},
body = { "url": "https://example.com/report" }
)
jobId = response.jobId
# 2) Poll status until job is done
loop:
wait a few seconds
statusResponse = HTTP_GET(
url = apiBase + "/jobs/" + jobId + "/status",
headers = { "Authorization": "Bearer " + apiKey }
)
status = statusResponse.status
if status == "FAILED":
stop with error
if status == "COMPLETED":
break loop
# 3) Download the resulting PDF/PNG
fileBytes = HTTP_GET(
url = apiBase + "/jobs/" + jobId + "/result",
headers = { "Authorization": "Bearer " + apiKey }
)
save fileBytes as "output.pdf"
You can translate this to Node, Python, Java, etc. I’ve put more concrete examples in the GitHub repo.
Where this is useful
- Invoices / billing PDFs that must match your UI
- Analytics dashboards and JS charts you need as PDF reports
- React / SPA routes like
/reports/123that rely on client-side rendering
Top comments (0)