typst-py
June 16, 2026 ยท View on GitHub
Python binding to typst, a new markup-based typesetting system that is powerful and easy to learn.
Installation
pip install typst
Usage
import datetime
import typst
# Compile `hello.typ` to PDF and save as `hello.pdf`
typst.compile("hello.typ", output="hello.pdf")
# Compile `hello.typ` to PNG and save as `hello.png`
typst.compile("hello.typ", output="hello.png", format="png", ppi=144.0)
# Or pass `hello.typ` content as bytes
with open("hello.typ", "rb") as f:
typst.compile(f.read(), output="hello.pdf")
# Or return PDF content as bytes
pdf_bytes = typst.compile("hello.typ")
# Use a fixed creation timestamp for reproducible PDFs
timestamp = datetime.datetime.fromtimestamp(0, datetime.timezone.utc)
pdf_bytes = typst.compile("hello.typ", timestamp=timestamp)
# Also for svg
svg_bytes = typst.compile("hello.typ", format="svg")
# Typst 0.15 minifies PDF, SVG, and HTML by default; pass pretty=True for
# human-readable export output.
svg_bytes = typst.compile("hello.typ", format="svg", pretty=True)
# Multiple compatible PDF standards can be requested at once.
pdf_bytes = typst.compile("hello.typ", pdf_standards=["a-2a", "ua-1"])
# For multi-page export (the template is the same as the typst cli)
images = typst.compile("hello.typ", output="hello{n}.png", format="png")
# Or use Compiler class to avoid reinitialization
compiler = typst.Compiler()
compiler.compile(input="hello.typ", format="png", ppi=144.0)
# Query something
import json
values = json.loads(typst.query("hello.typ", "<note>", field="value", one=True))
# Or use Typst's newer eval-style query expression
values = json.loads(typst.eval("hello.typ", "query(<note>).first().value"))
Multi-file projects
You can compile multi-file Typst projects by passing a dictionary mapping filenames to
their content as bytes. The entry point must be keyed as "main" or "main.typ" (if
there is only one file, any key works):
import typst
files = {
"main.typ": b'#import "lib.typ": greet\n= Hello\n#greet("World")',
"lib.typ": b'#let greet(name) = [Hello, #name!]',
}
pdf = typst.compile(files, format="pdf")
This is useful when Typst sources are bundled as Python package resources:
import typst
import importlib.resources
files = {}
for filename in ["main.typ", "lib.typ", "utils.typ"]:
files[filename] = importlib.resources.read_binary("mypackage.typst_files", filename)
pdf = typst.compile(files, format="pdf")
Dictionary values can also be file paths (as strings or Path objects), which will be
read from disk.
Packages
Use package_path to point Typst at a local package directory and
package_cache_path to control where downloaded @preview packages are cached:
import typst
pdf = typst.compile(
"main.typ",
package_path="vendor",
package_cache_path="vendor",
)
Passing values
You can pass values to the compiled Typst file with the sys_inputs argument. For example:
import json
import typst
persons = [{"name": "John", "age": 35}, {"name": "Xoliswa", "age": 45}]
sys_inputs = {"persons": json.dumps(persons)}
typst.compile(input="main.typ", output="ages.pdf", sys_inputs=sys_inputs)
The following example shows how the passed data can be used in a Typst file.
#let persons = json(bytes(sys.inputs.persons))
#for person in persons [
#person.name is #person.age years old. \
]
License
This work is released under the Apache-2.0 license. A copy of the license is provided in the LICENSE file.