Invalid Date

Generate PDFs from HTML with just a few lines of code. This guide walks you through the FUNBREW PDF API with step-by-step examples in Node.js, Python, and PHP. If you're migrating from Puppeteer or Playwright, see the Puppeteer migration guide.

Setup

1. Create an Account

Sign up for free. You get 30 PDF generations per month at no cost.

2. Get Your API Key

Navigate to the "API Keys" section in your dashboard and generate a key. It starts with sk-.

# Set as an environment variable (recommended)
export FUNBREW_PDF_API_KEY="sk-your-api-key"

For secure key management practices, see the security guide.

3. API Endpoint

POST https://api.pdf.funbrew.cloud/v1/pdf/from-html

Send HTML, get a PDF binary back. Simple request/response model.

Node.js

For TypeScript projects, see the TypeScript PDF API guide for type-safe implementations. For Next.js or Nuxt integrations, check the Next.js/Nuxt guide.

fetch (Built-in API)

Node.js 18+ includes fetch natively. No extra packages needed.

const fs = require('fs');

async function generatePdf() {
  const response = await fetch('https://api.pdf.funbrew.cloud/v1/pdf/from-html', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${process.env.FUNBREW_PDF_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      html: `
        <html>
          <head>
            <style>
              body { font-family: Arial, sans-serif; padding: 40px; }
              h1 { color: #1a1a1a; border-bottom: 2px solid #3b82f6; padding-bottom: 8px; }
              .info { color: #6b7280; margin-top: 24px; }
            </style>
          </head>
          <body>
            <h1>Report</h1>
            <p>This PDF was generated via the API.</p>
            <p class="info">Generated: ${new Date().toISOString()}</p>
          </body>
        </html>
      `,
      engine: 'quality',
      format: 'A4',
    }),
  });

  if (!response.ok) {
    throw new Error(`API error: ${response.status}`);
  }

  const pdf = Buffer.from(await response.arrayBuffer());
  fs.writeFileSync('output.pdf', pdf);
  console.log('PDF generated: output.pdf');
}

generatePdf();

axios

When using axios, setting the response type is key.

const axios = require('axios');
const fs = require('fs');

async function generatePdf() {
  const { data } = await axios.post(
    'https://api.pdf.funbrew.cloud/v1/pdf/from-html',
    {
      html: '<h1>Hello PDF</h1><p>Generated with axios</p>',
      engine: 'fast',
      format: 'A4',
    },
    {
      headers: { 'Authorization': `Bearer ${process.env.FUNBREW_PDF_API_KEY}` },
      responseType: 'arraybuffer',  // Required for binary response
    }
  );

  fs.writeFileSync('output.pdf', data);
  console.log('PDF generated: output.pdf');
}

generatePdf();

Python

For Django or FastAPI integrations, see the Django/FastAPI PDF API guide.

requests

The most popular HTTP library in Python.

import os
import requests

def generate_pdf():
    response = requests.post(
        'https://api.pdf.funbrew.cloud/v1/pdf/from-html',
        headers={
            'Authorization': f'Bearer {os.environ["FUNBREW_PDF_API_KEY"]}',
        },
        json={
            'html': '''
                <html>
                <head>
                    <style>
                        body { font-family: Arial, sans-serif; padding: 40px; }
                        h1 { color: #1a1a1a; }
                        table { width: 100%; border-collapse: collapse; margin-top: 20px; }
                        th, td { border: 1px solid #e5e7eb; padding: 12px; text-align: left; }
                        th { background: #f8fafc; }
                    </style>
                </head>
                <body>
                    <h1>Sales Report</h1>
                    <table>
                        <tr><th>Month</th><th>Revenue</th></tr>
                        <tr><td>January</td><td>$12,000</td></tr>
                        <tr><td>February</td><td>$13,500</td></tr>
                        <tr><td>March</td><td>$15,000</td></tr>
                    </table>
                </body>
                </html>
            ''',
            'engine': 'quality',
            'format': 'A4',
        },
        timeout=30,
    )
    response.raise_for_status()

    with open('report.pdf', 'wb') as f:
        f.write(response.content)
    print(f'PDF generated: report.pdf ({len(response.content)} bytes)')

generate_pdf()

httpx (Async Support)

For async workflows, httpx is a great choice.

import httpx
import asyncio
import os

async def generate_pdf():
    async with httpx.AsyncClient() as client:
        response = await client.post(
            'https://api.pdf.funbrew.cloud/v1/pdf/from-html',
            headers={'Authorization': f'Bearer {os.environ["FUNBREW_PDF_API_KEY"]}'},
            json={
                'html': '<h1>Async PDF</h1><p>Generated with httpx</p>',
                'engine': 'fast',
                'format': 'A4',
            },
            timeout=30,
        )
        response.raise_for_status()

    with open('output.pdf', 'wb') as f:
        f.write(response.content)
    print('PDF generated: output.pdf')

asyncio.run(generate_pdf())

PHP

For Ruby or Go code examples, see the Ruby/Go quickstart guide.

Laravel (Http Facade)

The most concise approach using Laravel's built-in HTTP client.

use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;

$response = Http::withToken(config('services.funbrew.api_key'))
    ->post('https://api.pdf.funbrew.cloud/v1/pdf/from-html', [
        'html' => '
            <html>
            <head>
                <style>
                    body { font-family: Arial, sans-serif; padding: 40px; }
                    h1 { color: #1a1a1a; }
                </style>
            </head>
            <body>
                <h1>Delivery Note</h1>
                <p>To: Acme Corp</p>
                <p>Total: $3,300.00 (incl. tax)</p>
            </body>
            </html>
        ',
        'engine' => 'quality',
        'format' => 'A4',
    ]);

if ($response->successful()) {
    Storage::put('pdfs/delivery-note.pdf', $response->body());
}

cURL (Framework-agnostic)

Plain PHP with cURL — works anywhere.

$ch = curl_init('https://api.pdf.funbrew.cloud/v1/pdf/from-html');

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => [
        'Authorization: Bearer ' . getenv('FUNBREW_PDF_API_KEY'),
        'Content-Type: application/json',
    ],
    CURLOPT_POSTFIELDS => json_encode([
        'html' => '<h1>Hello PDF</h1>',
        'engine' => 'fast',
        'format' => 'A4',
    ]),
]);

$pdf = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 200) {
    file_put_contents('output.pdf', $pdf);
}

Ruby

Use Ruby's standard library or the popular Faraday gem.

net/http (Standard Library)

require 'net/http'
require 'json'
require 'uri'

uri = URI('https://api.pdf.funbrew.cloud/v1/pdf/from-html')

http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

request = Net::HTTP::Post.new(uri)
request['Authorization'] = "Bearer #{ENV['FUNBREW_PDF_API_KEY']}"
request['Content-Type'] = 'application/json'
request.body = {
  html: '<h1>Hello from Ruby</h1><p>PDF generated with net/http</p>',
  engine: 'fast',
  format: 'A4'
}.to_json

response = http.request(request)

if response.code == '200'
  File.open('output.pdf', 'wb') { |f| f.write(response.body) }
  puts "PDF generated: output.pdf (#{response.body.bytesize} bytes)"
end

Faraday

require 'faraday'

conn = Faraday.new(url: 'https://api.pdf.funbrew.cloud') do |f|
  f.request :json
  f.headers['Authorization'] = "Bearer #{ENV['FUNBREW_PDF_API_KEY']}"
end

response = conn.post('/v1/pdf/from-html', {
  html: '<h1>Hello from Ruby</h1>',
  engine: 'quality',
  format: 'A4'
})

File.open('output.pdf', 'wb') { |f| f.write(response.body) } if response.success?

Go

Go's standard library is all you need — no external dependencies.

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"os"
)

func main() {
	payload, _ := json.Marshal(map[string]interface{}{
		"html":   "<h1>Hello from Go</h1>",
		"engine": "fast",
		"format": "A4",
	})

	req, _ := http.NewRequest("POST",
		"https://api.pdf.funbrew.cloud/v1/pdf/from-html",
		bytes.NewBuffer(payload))
	req.Header.Set("Authorization", "Bearer "+os.Getenv("FUNBREW_PDF_API_KEY"))
	req.Header.Set("Content-Type", "application/json")

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		fmt.Println("Error:", err)
		return
	}
	defer resp.Body.Close()

	if resp.StatusCode == 200 {
		pdf, _ := io.ReadAll(resp.Body)
		os.WriteFile("output.pdf", pdf, 0644)
		fmt.Printf("PDF generated: output.pdf (%d bytes)\n", len(pdf))
	}
}

Frequently Asked Questions

Can I use external CSS or web fonts in HTML?

Yes. Use <link> tags to load external stylesheets. Google Fonts and other web fonts work too. However, external resources add to generation time — for production, consider inline styles or self-hosted fonts.

Base64 or URL for images?

Small icons and logos (under 50 KB) work best as Base64-encoded data URIs. For larger images, use URL references to keep request size down. URL-referenced images must be publicly accessible.

How can I reduce PDF file size?

Use engine: "fast" for smaller files. Also: optimize image resolution, remove unused web fonts, and keep CSS minimal.

Choosing an Engine

FUNBREW PDF offers two rendering engines. Switch between them per request.

Engine Parameter Characteristics Best For
Fast "engine": "fast" High speed, lightweight Simple HTML, bulk generation
Quality "engine": "quality" High fidelity, full CSS Design-heavy, CSS Grid layouts

For technical details on engine differences, see wkhtmltopdf vs Chromium.

Next Steps

Once you have basic PDF generation working, explore these features:

Related

Powered by FUNBREW PDF