Library / SDK
QuestPDF/QuestPDF avatar
QuestPDF/QuestPDF

QuestPDF builds a PDF from nested C# lambdas, not from HTML

QuestPDF is a modern library for PDF document generation. Its fluent C# API lets you design complex layouts with clean, readable code. Create documents using a flexible, component-based approach.

14,222 stars774 forksC#NOASSERTION

At a glance

What is it?
QuestPDF is a C# PDF generation library whose fluent API expresses a page as a tree of containers, headers, columns, and rows. The layout code goes into version control, and the cost of that choice is layout operations the README names without arguments, a companion app you must fetch separately, and a free tier that ends at $1M in annual revenue.
Who is it for?
Adopt QuestPDF when the team writes C# and the document is generated from data, because page breaks, headers, and conditional rows become code a reviewer can read. Leave it if the job starts from a PDF someone else produced, since the README's feature list covers generation only, or if a working HTML-to-PDF pipeline already owns the layout and nobody on the team wants to maintain C#.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • QuestPDF/QuestPDF14,222 ★ · +39
Star history
Repository2026-09-222026-11-14
QuestPDF/QuestPDF14.2k14.2k

39 Stars in the last 53 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The page is a tree of nested lambdas, not a markup document

A QuestPDF document is built by handing nested lambdas to Document.Create. Inside the outermost lambda, container.Page receives a page, and page.Header and page.Content receive containers of their own. Every measurement is a method call carrying a value and a unit, so page.Margin(2, Unit.Centimetre) sets the margin and page.PageColor(Colors.White) sets the paper colour. Nothing in that chain emits HTML, and nothing produces a template you can hand to a designer for editing.

Once the tree is complete, the layout is resolved from it. That is the structural difference from an HTML-to-PDF pipeline, the alternative the project names directly: there you describe the page in markup and a renderer decides pagination, and you inherit CSS debugging and browser quirks along with it. Here the page is described in C# and the resolver is the library. What follows from that is a staffing question rather than a technical one. Whoever maintains an invoice template has to be able to read a method chain, and editing a stylesheet is not a way in.

Page flow is a list of named operations with no documented arguments

Under Content Flow, QuestPDF lists page breaks, prevent page breaks, ensure space, show entire, repeat, show once, skip once, conditional rendering, and stop paging. Every name is a separate call a developer has to remember to add, and none of them appears in the quick start. page.Header sits on the page rather than on the content, which is how a running header is expressed here, but a table that must stay whole on one page needs an explicit call nobody shows you.

The README names these operations without explaining them. Neither the quick start nor the feature list gives an argument list for show entire, skip once, or stop paging, states the default page-break behaviour, or says what happens when a single element is taller than the printable area. The names are all the README gives you. Past them you are in the documentation site linked at the top of the project page, and that is where the signatures live.

One NuGet command, and a license line that ships commented out

QuestPDF ships as a NuGet package with one terminal command. You can also search for the phrase QuestPDF in Visual Studio, Visual Code, or JetBrains Rider, and the project links out to the package management guides for those three IDEs.

bash
dotnet add package QuestPDF

The quick start then opens with a license line that arrives commented out.

csharp
// set your license here:
// QuestPDF.Settings.License = LicenseType.Evaluation;

The free tier covers individuals, non-profits, open-source projects, and organizations under $1M in annual gross revenue. That is a company-wide revenue figure, not a per-seat one, and it is the point at which the terms change. Neither the quick start nor the feature list says what the library does when no license type is set, or what a paying organization gets once it passes the threshold; the pricing page does. Copy the quick start, skip that link, and you have not answered the question that decides whether you may ship.

A padding change is a four-unit diff and an unreviewed page

The project's case for a code-based document is version control, and it illustrates the point with a diff.

diff
void ComposeItem(IContainer container, OrderItem item)
{
    container
        .Border(1, Colors.Grey.Darken2)
        .Background(item.HighlightColor)
-       .Padding(12)
+       .Padding(16)
        .Row(row =>
        {
            row.RelativeItem().Text(item.Name);
            row.AutoItem().Text($"{item.Price:F2} USD");
        });
}

Read what that diff carries and what it drops. One helper's padding grew by four units on a method that also sets a border, a per-item background, and a two-item row. Nothing in the diff says which pages redraw as a result, or how the price column sits beside the name once the name wraps. The reviewer is approving an API call, not a document. The project's answer to that gap is the Companion App and its live preview, and the consequence for a team that does not run it is that a one-character edit to a padding constant gets merged on the strength of an approval box.

Loops in the layout put the page count outside the review

Dynamic content is ordinary C# control flow. The project's example puts a condition and a loop straight inside a column definition.

csharp
container.Column(column =>
{
    column.Item().Text("Order Items").Bold();

    if (Model.ShowSummary)
        column.Item().Element(ComposeOrderSummary);

    foreach (var item in Model.Items)
        column.Item().Element(c => ComposeItem(c, item));
});

The shape of the page is a function of the data, settled while the file is being written. Three order items and three hundred run the same code path and produce different page counts, and reading that path cannot tell you which case you have. Inside the row, RelativeItem takes what is left after AutoItem claims the width its formatted price needs, so horizontal proportions are resolved from content at render time as well.

Nothing in the quick start or the feature list gives you a way to assert a page count, cap a table's height, or catch an element that overflows before the file leaves the build.

The Companion App carries the layout debugging, and its install is not here

Layout errors and runtime exceptions are what the Companion App is for. A live document preview comes with hot reload that works without recompiling, plus a document hierarchy to inspect, content to magnify and measure, and runtime exceptions shown with stack traces and the code around them.

What the quick start does not say is how to get it. No installer is named, no platform list is given, no version is matched against the 2026.9.1 package, and no statement says whether the app falls under the same free tier that covers individuals and organizations under $1M in revenue. The two links under its screenshots go to a usage page and a features page on questpdf.com. A developer on a build server, or a team that never runs the app, is left reading exception text, because no fallback inspector is described.

Fonts and images are named as features with no requirements attached

Internationalization occupies one line of the feature list: RTL layout direction, bidirectional text, advanced text shaping, font fallback, multilingual documents, and accessibility support. Visual content takes another: rich text, fonts, colors, raster images, SVG, placeholders, and canvas graphics. Neither line carries a requirement. Nothing in the quick start says how to register a font file, whether fonts end up embedded in the output or referenced from the system, what happens when a glyph is missing and fallback has to substitute, or what licence a font needs before you ship it inside a customer's document.

Images are the same story. Raster images and SVG are named, with no resolution, colour space, or file size guidance attached in the README. A team printing right-to-left invoices can confirm the features exist and still be unable to register the typeface from the README alone.

Source-available terms, a revenue ceiling, and one src tree

The repository root holds .gitattributes, .github/, .gitignore, LICENSE.md, README.md, and a single src/ directory. There is no sample project at the root; the README points to a Quick Start and an Invoice Tutorial on questpdf.com instead. The README describes the library as source-available and points to a licence page, while the terms themselves sit in LICENSE.md and the repository's licence field is left unresolved.

On upkeep, the last push was on 2026-10-29 and the repository is not archived. Releases carry the year and month in the version: 2026.8.0 on 2026-08-24, 2026.9.0 on 2026-09-14, 2026.9.1 on 2026-09-25. Since a document is a program, a package bump can change what your reports look like. The other boundary is scope: everything the README's feature list enumerates is generation-side.

Editorial conclusion

Adopt QuestPDF when the team writes C# and the document is generated from data, because page breaks, headers, and conditional rows become code a reviewer can read. Leave it if the job starts from a PDF someone else produced, since the README's feature list covers generation only, or if a working HTML-to-PDF pipeline already owns the layout and nobody on the team wants to maintain C#. Before you commit, read the pricing page, because the free tier stops at $1M in annual gross revenue and neither the quick start nor the pricing summary says what happens above that line.

Frequently asked questions

What is QuestPDF?

QuestPDF is a C# library for generating PDF documents, built on a fluent API where nested lambdas describe the page tree: containers, pages, headers, content, columns, and rows. Documents are written as code rather than as markup passed to a renderer.

Is QuestPDF free?

The library is free for individuals, non-profits, open-source projects, and organizations under $1M in annual gross revenue. A pricing page covers the terms above that threshold, and the quick start ships with the license type line commented out.

Is QuestPDF open source?

The project describes itself as source-available rather than open source, and the licence text sits in LICENSE.md at the repository root. Usage rights are decided by who you are and by your annual gross revenue, not by the licence alone.

How do I use QuestPDF in C#?

Add the package with dotnet add package QuestPDF, then build the document with Document.Create, defining pages through container.Page and filling them with page.Header and page.Content. Loops, conditions, and helper methods are written as ordinary C# inside the layout.

How do I use the QuestPDF companion app?

The companion app gives a live document preview with hot reload that works without recompiling, and lets you inspect the document hierarchy, measure content, and read runtime exceptions with stack traces. The README links to usage and features pages on questpdf.com, which is where to look for setup.

What is the best C# library for generating PDFs?

The project does not rank itself against other C# PDF libraries. It argues for a fluent, component-based C# API over HTML-to-PDF conversion, and states that the free tier covers individuals, non-profits, open-source projects, and organizations under $1M in revenue.

Official sources

  1. Issues
  2. Project website
  3. QuestPDF/QuestPDF on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/questpdf-questpdf.svg)](https://hysenlabs.com/projects/questpdf-questpdf)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/questpdf-questpdf.svg)](https://hysenlabs.com/projects/questpdf-questpdf)

Was this useful?