# Automate PDF reports from your data PDF report automation: query your data, build HTML with SVG or Chart.js charts, add page numbers, render to PDF on a schedule and email it. Weekly KPI summaries, monthly client reports and end-of-day sales digests are usually the same layout with new numbers. Instead of copying charts into a document every week, build the report as HTML from your data. A scheduled job then turns it into a PDF. **Quick answer.** Build the report as HTML, then POST it to `https://html-pdf.com/v1/pdf` from a scheduled job and save or email the result. ```bash curl https://html-pdf.com/v1/pdf -H "Authorization: Bearer $HTML_PDF_KEY" \ -d '{"html":"

Weekly sales report

Revenue: $4,210

"}' -o weekly-report.pdf ``` ## The pipeline These are the five steps every automated report goes through. 1. **Query** your database, warehouse or analytics API. 2. **Build HTML**: tables for numbers, SVG or Chart.js for charts. 3. **Render** with `POST https://html-pdf.com/v1/pdf`. 4. **Deliver**: email the PDF, upload it to storage, or post the link to a chat channel. 5. **Schedule** the whole thing with cron, GitHub Actions or a workflow tool such as n8n. The free [report template](https://html-pdf.com/templates/report) gives you a starting layout with a title block, KPI cards and a table. ## Build the HTML from query results (Python) This script turns a SQL query into a report with an SVG bar chart, a table and page numbers. ```python import os, html, sqlite3, requests db = sqlite3.connect("shop.db") rows = db.execute(""" SELECT date(created_at) AS day, COUNT(*) AS orders, SUM(total) AS revenue FROM orders WHERE created_at >= date('now', '-7 day') GROUP BY day ORDER BY day """).fetchall() max_rev = max((r[2] for r in rows), default=0) or 1 bars = "".join( f'' f'{html.escape(r[0][5:])}' for i, r in enumerate(rows)) table = "".join(f"{html.escape(d)}{o}${rev:,.2f}" for d, o, rev in rows) page = f"""

Weekly sales report

{bars}
{table}
DayOrdersRevenue
""" r = requests.post("https://html-pdf.com/v1/pdf", headers={"Authorization": f"Bearer {os.environ['HTML_PDF_KEY']}"}, json={ "html": page, "format": "A4", "margin": {"top": "15mm", "right": "12mm", "bottom": "18mm", "left": "12mm"}, "footer_html": '
' 'Page of
', "max_pages": 20, }, timeout=60) r.raise_for_status() open("weekly-report.pdf", "wb").write(r.content) ``` The doubled braces in the CSS are Python f-string escaping. Server-side SVG is the most predictable option for charts. There is no JavaScript to wait for, and the output is sharp at any zoom. ## Charts with Chart.js This section shows how to use Chart.js if your team already relies on it. Load it from a CDN, turn animations off, and tell the renderer when the chart is ready with `wait_for_expression`. ```html ``` Send it with `"wait_for_expression": "window.chartReady === true"`. More detail in [Chart.js to PDF](https://html-pdf.com/chartjs-to-pdf). ## Page numbers and page breaks This section keeps multi-page reports readable. `footer_html` uses Chrome's placeholders (`pageNumber`, `totalPages`) and needs a bottom margin to have room. CSS `@page` margin boxes such as `@bottom-center { content: counter(page) }` also work in Chromium. Keep tables readable with a repeating `thead` and `break-inside: avoid` on rows and charts. See [headers, footers and page numbers](https://html-pdf.com/pdf-headers-footers-page-numbers) and [page breaks](https://html-pdf.com/html-to-pdf-page-breaks). ## Schedule it These examples run the report script automatically every Monday at 07:00. **cron** on any server: ``` 0 7 * * 1 cd /opt/reports && HTML_PDF_KEY=... python3 weekly_report.py ``` **GitHub Actions**: ```yaml name: weekly-report on: schedule: - cron: "0 7 * * 1" jobs: report: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - run: pip install requests - run: python weekly_report.py env: HTML_PDF_KEY: ${{ secrets.HTML_PDF_KEY }} - uses: actions/upload-artifact@v4 with: { name: weekly-report, path: weekly-report.pdf } ``` Scheduled workflows run in UTC. **n8n** uses a Schedule Trigger, a database node, a Code node that builds the HTML, then an HTTP Request node calling the API. See the [n8n guide](https://html-pdf.com/guides/n8n). ## Email the PDF This section covers getting the report to people. Attach the file with your mail provider's SDK or SMTP. If you'd rather send a link, request `"response": "url"`. The API returns a download URL that stays valid for 24 hours, which suits a "this week's report" email. For anything that must live longer, upload the binary to your own storage. ## Automate reports with html-pdf.com This is what you get with the hosted API. html-pdf.com is a Chromium-based HTML and URL to PDF API with page-based pricing. You get 100 free credits, then from $0.005 per page, and purchased credits never expire. A 4-page weekly report costs 4 credits. Requests can be up to 20 MB and render for up to 30 seconds, and your HTML is not stored. With the [MCP server](https://html-pdf.com/pdf-mcp-server), an AI agent can produce the report straight from data you paste or query. > *"Take this CSV of last month's sales by region, build a two-page PDF report with a bar chart per region, a summary table and page numbers in the footer, and give me the link."* [Get an API key](https://html-pdf.com/login) ## FAQ ### How do I automate PDF reports from a database? Query your data, build an HTML page with tables and SVG or Chart.js charts, and POST it to `https://html-pdf.com/v1/pdf`. Run the script on a schedule with cron, GitHub Actions or n8n. ### How do I include Chart.js charts in a PDF report? Turn animations off and set a flag such as `window.chartReady = true` once the chart is drawn. Then send `"wait_for_expression": "window.chartReady === true"` so the renderer waits for it. ### How much does an automated PDF report cost? 1 credit = 1 PDF page, so a 4-page weekly report costs 4 credits. You get 100 free credits once, then packs from $10 for 1,000 pages to $250 for 50,000 pages. ### Can I email a link instead of attaching the PDF? Yes. Request `"response": "url"` and the API returns a download link that lasts 24 hours. For longer storage, upload the PDF to your own storage.