Golang HTML to PDF Code Examples

Complete Go examples for common HTML to PDF tasks. See the Go SDK guide for installation and result handling.

You can run the examples below with the displayed API credentials. Update the input URLs and filenames as needed. Each Go example can be copied and run independently.

Basic examples

Choose file, in-memory, or output-stream handling for the result. Stream examples use a file stream as their destination.

Convert a URL

Save to a file

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    err := client.ConvertUrlToFile("https://example.com/", "example.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Keep in memory

package main

import (
    "log"
    "fmt"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    pdf, err := client.ConvertUrl("https://example.com/") // []byte
    checkError(err)
    fmt.Println(len(pdf))
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Write to a stream

package main

import (
    "log"
    "os"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    output_stream, err := os.Create("example.pdf")
    checkError(err)
    err = client.ConvertUrlToStream("https://example.com/", output_stream)
    closeErr := output_stream.Close()
    checkError(err)
    checkError(closeErr)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Convert an HTML file

Upload an existing document.html file. For local images and stylesheets, see Local assets.

Save to a file

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    err := client.ConvertFileToFile("document.html", "document.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Keep in memory

package main

import (
    "log"
    "fmt"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    pdf, err := client.ConvertFile("document.html") // []byte
    checkError(err)
    fmt.Println(len(pdf))
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Write to a stream

package main

import (
    "log"
    "os"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    output_stream, err := os.Create("document.pdf")
    checkError(err)
    err = client.ConvertFileToStream("document.html", output_stream)
    closeErr := output_stream.Close()
    checkError(err)
    checkError(closeErr)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Send HTML content

These examples read HTML text from document.html. In an application, pass the HTML produced by your template renderer instead.

Save to a file

package main

import (
    "log"
    "os"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    htmlBytes, err := os.ReadFile("document.html")
    checkError(err)
    html := string(htmlBytes)
    client.SetContentViewportWidth("balanced")
    err = client.ConvertStringToFile(html, "html.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Keep in memory

package main

import (
    "log"
    "os"
    "fmt"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    htmlBytes, err := os.ReadFile("document.html")
    checkError(err)
    html := string(htmlBytes)
    client.SetContentViewportWidth("balanced")
    pdf, err := client.ConvertString(html) // []byte
    checkError(err)
    fmt.Println(len(pdf))
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Write to a stream

package main

import (
    "log"
    "os"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    htmlBytes, err := os.ReadFile("document.html")
    checkError(err)
    html := string(htmlBytes)
    client.SetContentViewportWidth("balanced")
    output_stream, err := os.Create("html.pdf")
    checkError(err)
    err = client.ConvertStringToStream(html, output_stream)
    closeErr := output_stream.Close()
    checkError(err)
    checkError(closeErr)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Convert inline HTML

Define a small HTML document directly in your code.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    html := `
        <!doctype html>
        <html><body><h1>Monthly report</h1></body></html>`

    client.SetContentViewportWidth("balanced")
    err := client.ConvertStringToFile(html, "report.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Read from an input stream

Open document.html as a binary input stream and save the PDF to document.pdf.

package main

import (
    "log"
    "os"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    input_stream, err := os.Open("document.html")
    checkError(err)
    err = client.ConvertStreamToFile(input_stream, "document.pdf")
    closeErr := input_stream.Close()
    checkError(err)
    checkError(closeErr)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Local assets

Include HTML and its local images, stylesheets, and scripts in a ZIP archive, keeping their relative paths.

Convert a prepared archive

Upload an existing document.zip. Select the main HTML file explicitly when the archive contains multiple documents.

Detect the main HTML file

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    err := client.ConvertFileToFile("document.zip", "output.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Select index.html

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetZipMainFilename("index.html")
    err := client.ConvertFileToFile("document.zip", "document.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Convert a local directory

Create document.zip from the existing document directory, then convert it to PDF.

package main

import (
    "archive/zip"
    "log"
    "os"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    archive, err := os.Create("document.zip")
    checkError(err)
    writer := zip.NewWriter(archive)
    err = writer.AddFS(os.DirFS("document"))
    zipErr := writer.Close()
    closeErr := archive.Close()
    checkError(err)
    checkError(zipErr)
    checkError(closeErr)

    client.SetContentViewportWidth("balanced")
    err = client.ConvertFileToFile("document.zip", "document.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Create an archive in memory

Package the existing document directory in memory. Its index.html file can refer to other files in the directory by relative path.

package main

import (
    "archive/zip"
    "bytes"
    "log"
    "os"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    var archive bytes.Buffer
    writer := zip.NewWriter(&archive)
    err := writer.AddFS(os.DirFS("document"))
    closeErr := writer.Close()
    checkError(err)
    checkError(closeErr)

    client.SetContentViewportWidth("balanced")
    client.SetZipMainFilename("index.html")
    err = client.ConvertStreamToFile(&archive, "document.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Page rendering

Set page size and margins

Use landscape Letter pages with half-inch margins.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetMarginBottom("0.5in")
    client.SetMarginLeft("0.5in")
    client.SetMarginRight("0.5in")
    client.SetMarginTop("0.5in")
    client.SetOrientation("landscape")
    client.SetPageSize("Letter")
    err := client.ConvertUrlToFile("https://example.com/", "page-layout.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Add a header and page numbers

Show the source URL in the header and “Page N of M” in the footer.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetFooterHeight("10mm")
    client.SetFooterHtml(`
        <center>
            Page <span class="pdfcrowd-page-number"></span>
            of <span class="pdfcrowd-page-count"></span>
        </center>`)
    client.SetHeaderHeight("15mm")
    client.SetHeaderHtml(`
        <a class="pdfcrowd-source-url"
            data-pdfcrowd-placement="href-and-content"></a>`)
    client.SetMarginBottom("0")
    client.SetMarginTop("0")
    err := client.ConvertUrlToFile("https://example.com/", "header_footer.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

See the headers and footers guide for more layouts and placeholders.

Scale page content

Scale the HTML content to 300%.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetScaleFactor(300)
    err := client.ConvertUrlToFile("https://example.com/", "zoom_300.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Choose a responsive layout

The browser viewport controls responsive breakpoints independently of the PDF paper size.

Large viewport

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("large")
    client.SetNoMargins(true)
    err := client.ConvertUrlToFile("https://example.com/", "bootstrap.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Small viewport

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("small")
    err := client.ConvertUrlToFile("https://example.com/", "viewport_small.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Hide or restyle page elements

Replace the selectors with elements from your page.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetCustomCss(`
        /* Hide navigation, ads, and sidebar */
        nav, .advertisement, .sidebar, footer {
            display: none !important;
        }
        /* Adjust layout for print */
        .content {
            width: 100% !important;
            max-width: none !important;
        }`)
    err := client.ConvertUrlToFile("https://example.com/", "custom_css.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Modify the page with JavaScript

Adjust the selectors and class names for your page.

Remove widgets and expand sections

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetCustomJavascript(`
        // Remove dynamic content before conversion
        document.querySelectorAll('.video-player, .chat-widget').forEach(el => {
            el.remove();
        });
        // Expand collapsed sections
        document.querySelectorAll('.collapsed').forEach(el => {
            el.classList.remove('collapsed');
        });`)
    err := client.ConvertUrlToFile("https://example.com/", "custom_js.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Add content to the page

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetCustomJavascript(`
        el = document.createElement('h2');
        el.textContent = 'Hello from PDFCrowd API';
        el.style.color = 'red';
        el_before = document.getElementsByTagName('h1')[0];
        el_before.parentNode.insertBefore(el, el_before.nextSibling);`)
    err := client.ConvertUrlToFile("https://example.com/", "html_inject.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Convert a specific element

Convert only #main in an existing document.html file. Adjust the filename and selector for your document.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetElementToConvert("#main")
    err := client.ConvertFileToFile("document.html", "html_part.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Wait for a page element

Wait for #content-loaded to appear in an existing document.html file. Choose an element that appears when your content is ready.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetWaitForElement("#content-loaded")
    err := client.ConvertFileToFile("document.html", "wait_element.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Allow extra time for JavaScript

Add a delay of 2000 milliseconds. When the page has a reliable readiness marker, use Wait for a page element.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetJavascriptDelay(2000)
    err := client.ConvertUrlToFile("https://example.com/", "with_delay.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Apply the page’s @media print rules. The page must provide print styles for this to change its appearance.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetUsePrintMedia(true)
    err := client.ConvertUrlToFile("https://example.com/", "print_media.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Inspect element boundaries

Highlight element boxes to investigate spacing and layout.

Highlight backgrounds

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetCustomJavascript(`
        libPdfcrowd.highlightHtmlElements({
            backgroundColor: 'rgba(255, 191, 0, 0.1)',
            borderColor: null
        });`)
    err := client.ConvertUrlToFile(
        "https://example.com/", "highlight_background.pdf",
    )
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Add borders and spacing

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetCustomJavascript(`
        libPdfcrowd.highlightHtmlElements({
            borderColor: 'orange',
            backgroundColor: null,
            padding: '4px',
            margin: '4px'
        });`)
    err := client.ConvertUrlToFile(
        "https://example.com/", "highlight_borders.pdf",
    )
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

HTML and CSS

Add these fragments to HTML you control.

Remove or hide elements

<nav class="pdfcrowd-remove">This won't appear in the PDF</nav>
<div class="pdfcrowd-hide">This is invisible but takes up space</div>

pdfcrowd-remove removes the element from the layout. pdfcrowd-hide preserves its space.

Control page breaks

<!-- Force a page break before the following section -->
<div style="page-break-before: always"></div>

<!-- Avoid breaking tables across pages -->
<style>
  table, tr, td { page-break-inside: avoid; }
</style>

Content taller than a page still needs to break.

Apply styles only during conversion

<style>
  /* These styles only apply during PDF conversion */
  .pdfcrowd-body h1 { font-size: 48px; }
  .pdfcrowd-body footer { display: none; }
  .pdfcrowd-body .main-content { width: 100%; }
</style>

The .pdfcrowd-body prefix limits these rules to conversion; it does not change the page in a visitor’s browser.

Templates

Render a template with JSON data

Upload existing template.html and data.json files. See the template rendering guide for template syntax, data mapping, and other supported data formats.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetDataFormat("json")
    client.SetDataFile("data.json")
    err := client.ConvertFileToFile("template.html", "output.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

PDF features

Create a fillable PDF

Use an existing form.html file containing HTML form controls.

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetContentViewportWidth("balanced")
    client.SetEnablePdfForms(true)
    err := client.ConvertFileToFile("form.html", "form.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

See fillable PDF forms for supported controls and attributes.

Set PDF metadata

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetAuthor("PDFCrowd")
    client.SetKeywords("PDFCrowd,demo")
    client.SetSubject("Demo")
    client.SetTitle("Hello World")
    err := client.ConvertUrlToFile("https://example.com/", "with_metadata.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

Set a presentation view

package main

import (
    "log"
    "github.com/pdfcrowd/pdfcrowd-go"
)

func main() {
    client := pdfcrowd.NewHtmlToPdfClient("demo", "demo")

    client.SetInitialZoomType("fit-page")
    client.SetNoMargins(true)
    client.SetOrientation("landscape")
    client.SetPageLayout("single-page")
    client.SetPageMode("full-screen")
    err := client.ConvertUrlToFile("https://example.com/", "slide_show.pdf")
    checkError(err)
}

func checkError(err error) {
    if err != nil {
        log.Fatal(err)
    }
}

These settings request a full-screen initial view with landscape pages. The PDF viewer controls whether it honors those preferences.