CLI reference
Every option of the sghtmltopdf command.
sghtmltopdf [OPTIONS] <INPUT.HTML>
sghtmltopdf server [OPTIONS]
The first converts a file; the second runs the HTTP server.
For how these map to wkhtmltopdf’s options, including the full list of the ones that are not supported, see the wkhtmltopdf option mapping.
Basics
# The simplest form; the system fonts are used
sghtmltopdf invoice.html -o invoice.pdf
# Without an output path, the input name with the extension changed to .pdf
sghtmltopdf invoice.html
# Read from standard input and write to standard output
cat invoice.html | sghtmltopdf - -o - > invoice.pdf
Input and output
| Option | Default | Description |
|---|---|---|
<INPUT.HTML> | (required) | The input HTML; - means standard input |
-o, --output <PATH> | The input name with .pdf | Where to write. - means standard output. It cannot be omitted when reading from standard input |
--base-url <URL|DIR> | The directory of the input HTML | The base for resolving relative references. An http(s) URL becomes the default <base href>; a <base href> in the HTML wins |
--encoding <NAME> | Detected | The character encoding of the input. The order is BOM, then --encoding, then <meta charset>, then UTF-8 |
--streaming | Off | Process in streaming mode |
The output is written to a temporary file and then renamed, so a failure never leaves a broken PDF behind.
Page setup
| Option | Default | Description |
|---|---|---|
-s, --page-size <SIZE> | A4 | A3, A4, A5, Letter, or Legal, case insensitive |
--page-width <LENGTH> | The paper width; takes precedence over --page-size | |
--page-height <LENGTH> | The paper height; takes precedence over --page-size | |
-O, --orientation <O> | Portrait | Landscape swaps width and height at the end |
-T, --margin-top <LENGTH> | 1in (96px) | Top margin |
-B, --margin-bottom <LENGTH> | 1in | Bottom margin |
-L, --margin-left <LENGTH> | 1in | Left margin |
-R, --margin-right <LENGTH> | 1in | Right margin |
Lengths take the units mm, cm, in, pt, and px. A bare number means mm, as in wkhtmltopdf.
How this relates to
@pagein CSSThese options are initial values. If the CSS in the HTML says
@page { size: … }or@page { margin: … }, the CSS wins, property by property. Note that this is the opposite of wkhtmltopdf.
Fonts
| Option | Description |
|---|---|
--font <PATH> | The font to use; may be given more than once. Without it, system fonts are used |
--font-index <N> | The face index inside a TrueType Collection (.ttc), for the preceding --font |
--gothic-font <PATH> (with --gothic-font-index) | The font behind font-family: sans-serif |
--serif-font <PATH> (with --serif-font-index) | The font behind font-family: serif |
--mono-font <PATH> (with --mono-font-index) | The font behind font-family: monospace |
Fonts are resolved in the order --font, then @font-face, then a system search by font-family name. Only if none of those finds anything does a system sans-serif candidate become the default font.
Without
--font, the output depends on the fonts of the machine it runs on. To keep output stable on a server or in CI, name the fonts with--fontor@font-face. See Fonts for details.
PDF output and metadata
| Option | Default | Description |
|---|---|---|
--title <TEXT> | The <title> of the HTML | The /Title of the PDF |
--author, --subject, --keywords <TEXT> | The matching entries of the Info dictionary; specific to sghtmltopdf | |
-d, --dpi <DPI> | 96 | How many dpi a CSS px stands for. At 72, 1px equals 1pt |
--zoom <FACTOR> | 1.0 | A scale factor, multiplied into the --dpi factor |
-g, --grayscale | Off | Convert fills and strokes to greyscale, by sRGB relative luminance |
--no-pdf-compression | Off | Turn off Flate compression of PDF objects; image data is unaffected |
/Producer and /CreationDate are always written.
The limits of greyscale
JPEG images, which pass through as
/DCTDecode, and CMYK images have no decoder here, so they stay in colour.
What gets drawn
| Option | Description |
|---|---|
--no-images | Do not load <img> or the CSS background-image |
--no-background | Do not paint element backgrounds, neither colour nor image |
--user-style-sheet <PATH> | CSS in the user origin; may be given more than once. Stronger than the UA stylesheet, weaker than the author’s CSS |
--minimum-font-size <PX> | A lower bound on the computed font-size |
--disable-external-links | Do not create PDF annotations for external http(s) links |
--disable-internal-links | Do not create PDF annotations for internal #id links |
--keep-relative-links | Write relative external links as they are, without making them absolute |
--load-media-error-handling <ignore|abort> | What to do when an image, stylesheet, or font cannot be fetched; ignore by default |
Headers and footers
There are two ways to do this. If both are given for the same side, --header-html wins.
1. As text
These map onto the margin boxes of @page.
sghtmltopdf report.html \
--header-center "Quarterly report" \
--footer-right "[page] / [topage]" \
--header-line
| Option | Description |
|---|---|
--header-left, --header-center, --header-right <TEXT> | The three positions across the header |
--footer-left, --footer-center, --footer-right <TEXT> | The three positions across the footer |
--header-font-name, --header-font-size | The header font; the footer has the same pair |
--header-line, --footer-line | Draw a rule |
--header-spacing, --footer-spacing <MM> | The gap from the body text; the margin grows by that much |
--default-header | A default header with the title and the page number |
--replace <NAME=VALUE> | Replace any [NAME] with a value; may be given more than once |
The placeholders are [page] for the current page, [topage] for the total page count, [frompage], [title] and [doctitle], [date], [time], and any name you define with --replace.
[section], [subsection], [webpage], [sitepage], and [sitepages] are not supported.
2. As HTML
sghtmltopdf report.html --header-html header.html --footer-html footer.html
A separate HTML file is rendered into the margin area of every page. Placeholders are substituted in the HTML as text; JavaScript is not executed.
- Anything that does not fit in the margin is clipped; the margin does not grow to accommodate it
- No external resources are fetched. Inline
<style>, text, borders, and background colours work;<img>and external CSS do not @font-faceinside the header or footer HTML is not loaded. Name any font used only there with--font
Cover page and table of contents
sghtmltopdf report.html --cover cover.html --toc --footer-center "[page]"
They are written in the order cover, table of contents, body.
| Option | Default | Description |
|---|---|---|
--cover <PATH> | The HTML to use as the cover. It is not counted in the page numbers and gets no header or footer | |
--toc | Off | Insert a table of contents before the body; not available in streaming mode |
--toc-header-text <TEXT> | Table of Contents | The <h1> of the table of contents |
--toc-level-indentation <WIDTH> | 1em | The indent added per level |
--toc-text-size-shrink <REAL> | 0.8 | The text size ratio applied per level |
--disable-dotted-lines | (drawn) | Do not draw the dotted leader under each entry |
--disable-toc-links | (linked) | Do not link the entries to their headings |
--enable-toc-back-links | (not linked) | Link each heading back to the table of contents |
--page-offset <N> | 0 | Shift where the page numbering starts |
The HTML structure and default styling of the table of contents follow what wkhtmltopdf’s default TOC XSL produces: nested <ul> for the levels, and <div><a>heading</a><span>page number</span></div> for each entry. To change how it looks, apply CSS with --user-style-sheet; XSLT is not supported.
Headings are collected from h1 through h6. A heading without an id is given a generated destination name.
Access control
| Option | CLI default | Server default |
|---|---|---|
--enable-local-file-access, --disable-local-file-access | Allowed | Denied |
--allow <PATH> | No restriction | No restriction |
--allow-remote-assets | Denied | Denied |
Given one or more --allow paths, local references are confined to those directories. This applies to <img src>, external CSS, and @font-face alike.
Ranges
References outside the base directory
Local references stay inside the base directory (--base-url, defaulting to the directory the input HTML lives in) by default. A ../ that would escape it is an error. This keeps untrusted HTML from reading arbitrary files through a reference such as <img src="../../../../etc/passwd">.
A ../ that resolves within the base directory, such as assets/../images/logo.png, keeps working as before.
Ranges
$ sghtmltopdf pages/index.html -o out.pdf
エラー: ../images/logo.png: 基準ディレクトリ(pages)の外を参照しています。
外部のファイルを読む場合は --allow でディレクトリを明示してください
$ sghtmltopdf pages/index.html --allow . -o out.pdf
The check is lexical, so symlinks under the base directory are followed. Use --allow when you want the boundary to hold across symlinks as well (that check resolves real paths).
Limits on input size
HTML with more than roughly 500,000 nodes is rejected. Computed styles, the box tree and the layout result all grow in proportion to the node count; measured at 472 B to 1210 B per node.
Even a document of several thousand pages stays in the hundreds of thousands of nodes, so real documents practically never hit this. If you do hit it, split the document or use streaming mode. Streaming releases each processed part as it goes, so it can convert documents whose total exceeds the limit.
Memory that scales with the amount of text is not covered by this limit (three elements holding 10 MiB of text still use about 1.7 GiB). In HTTP server mode --max-body-size plays that role.
Logging and exit codes
--log-level <none|error|warn|info>, info by default, and -q or --quiet, which is the same as --log-level none.
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Usage error: an unknown option, a malformed value, or an option that is not supported |
| 2 | Input or resource error: a missing file, a font that cannot be read, or a failed fetch under abort |
| 3 | Rendering error, such as breaking one of the streaming mode restrictions |
| 4 | Time limit exceeded (HTTP server mode’s --timeout only; the CLI has no time limit, so this never appears) |