CobaltPDF.Requests
1.6.0
Prefix Reserved
dotnet add package CobaltPDF.Requests --version 1.6.0
NuGet\Install-Package CobaltPDF.Requests -Version 1.6.0
<PackageReference Include="CobaltPDF.Requests" Version="1.6.0" />
<PackageVersion Include="CobaltPDF.Requests" Version="1.6.0" />
<PackageReference Include="CobaltPDF.Requests" />
paket add CobaltPDF.Requests --version 1.6.0
#r "nuget: CobaltPDF.Requests, 1.6.0"
#:package CobaltPDF.Requests@1.6.0
#addin nuget:?package=CobaltPDF.Requests&version=1.6.0
#tool nuget:?package=CobaltPDF.Requests&version=1.6.0
CobaltPDF.Requests
Generate PDFs from your app — without putting a browser in it.
CobaltPDF.Requests is a tiny (~50 KB) package of two plain C# models: PdfRequest and PdfResponse.
Your app describes the PDF it wants as a PdfRequest, sends it as JSON to a
CobaltPDF rendering service you host, and gets the finished
PDF back.
The service does all the heavy lifting (Chromium or WebKit). Your web API, mobile backend, or serverless function stays small and fast — no Chromium, no rendering engine, no native libraries to install.
YOUR APP YOUR PDF SERVICE (you host once)
CobaltPDF.Requests · ~50 KB CobaltPDF or CobaltPDF.WebKit
no browser, no engine the real render engine + warm pool
build a PdfRequest ───── POST as JSON ─────▶ request.ExecuteAsync(engine)
save the PDF ◀───── PDF bytes ────────── renders & returns the PDF
Engine-agnostic. The same serialised
PdfRequestrenders on a service backed by either CobaltPDF (Chromium) or CobaltPDF.WebKit — clients never need to know which engine is on the other end.
Installation
Client (web app, mobile backend, other service):
dotnet add package CobaltPDF.Requests
Rendering service (Azure Function, ASP.NET Core, AWS Lambda, worker):
dotnet add package CobaltPDF
# CobaltPDF.Requests models are included automatically
Quick start — client
Build a request with the fluent builder, POST it to your service, and save the PDF:
using CobaltPdf.Requests;
using System.Net.Http.Json;
var request = PdfRequest.ForUrl("https://myapp.com/invoice/42")
.WithPaperFormat("A4")
.WithHeader("<div style='font-size:10px;text-align:center;width:100%'>My Company</div>")
.WithFooter("Page <span class='pageNumber'></span> of <span class='totalPages'></span>")
.WithMetadata(m => { m.Title = "Invoice #42"; m.Author = "Billing System"; })
.WithEncryption("open123")
.AddCookie("session", "abc123", "myapp.com")
.Build();
var httpResponse = await httpClient.PostAsJsonAsync("https://pdf-service/api/pdf", request);
httpResponse.EnsureSuccessStatusCode();
// Option A — raw PDF bytes (Content-Type: application/pdf)
byte[] pdfBytes = await httpResponse.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("invoice.pdf", pdfBytes);
// Option B — PdfResponse JSON (Content-Type: application/json)
var pdfResponse = await httpResponse.Content.ReadFromJsonAsync<PdfResponse>();
byte[] pdfBytes2 = pdfResponse!.ToBytes();
Prefer plain objects? The object-initializer style works identically — see Two ways to build a request below.
Two ways to build a request
PdfRequest is a plain serialisable model — use whichever style you prefer. Both produce the exact same request (identical JSON on the wire).
Fluent builder (recommended) — mirrors the CobaltEngine fluent API, so authoring a request reads the same as rendering one:
var request = PdfRequest.ForUrl("https://bbc.co.uk") // or PdfRequest.ForHtml("<h1>Hi</h1>")
.WithPaperFormat("A4")
.WithMargins("15mm")
.AddCookie("ckns_explicit", "1", ".bbc.co.uk")
.WithHeader("<div style='font-size:9px;text-align:center;width:100%'>My Company</div>")
.WithMetadata(m => { m.Title = "Invoice #42"; m.Author = "Billing System"; })
.Build(); // returns a PdfRequest
.Build() returns an ordinary PdfRequest, so everything downstream (serialisation, ExecuteAsync on the server) is unchanged. Already have a PdfRequest? Call .ToBuilder() to tweak it fluently. The builder covers the whole model — WithLandscape, WithFooter, WithWatermark, WithWaitStrategy, WithLazyLoadPages, WithHttpHeader(s), AddLocalStorage/AddSessionStorage, WithEncryption, and more.
Object initializer — the classic style, idiomatic for data shapes:
var request = new PdfRequest
{
Url = "https://bbc.co.uk",
PaperFormat = "A4",
Margins = new PdfRequestMargins { Top = "15mm", Right = "15mm", Bottom = "15mm", Left = "15mm" },
Cookies = { new PdfRequestCookie { Name = "ckns_explicit", Value = "1", Domain = ".bbc.co.uk" } }
};
Quick start — server
ASP.NET Core Minimal API
using CobaltPdf;
using CobaltPdf.Configuration;
using CobaltPdf.Extensions;
using CobaltPdf.Requests;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddCobaltPdf(o =>
{
CloudEnvironment.ConfigureForDocker(o);
o.MaxSize = Math.Max(2, Environment.ProcessorCount);
});
var app = builder.Build();
CobaltEngine.SetLicense(app.Configuration["CobaltPdf:LicenseKey"]!);
await CobaltEngine.PreWarmAsync();
// POST /api/pdf → raw PDF bytes
app.MapPost("/api/pdf", async (PdfRequest request, CobaltEngine renderer, CancellationToken ct) =>
{
var pdf = await request.ExecuteAsync(renderer, ct);
return Results.File(pdf.BinaryData, "application/pdf", "output.pdf");
});
// POST /api/pdf/json → PdfResponse JSON (service-to-service)
app.MapPost("/api/pdf/json", async (PdfRequest request, CobaltEngine renderer, CancellationToken ct) =>
{
var pdf = await request.ExecuteAsync(renderer, ct);
return Results.Ok(PdfResponse.FromBytes(pdf.BinaryData));
});
app.Run();
Azure Function (Isolated Worker)
[Function("GeneratePdf")]
public async Task<HttpResponseData> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = "pdf")]
HttpRequestData req, CancellationToken ct)
{
var request = await req.ReadFromJsonAsync<PdfRequest>();
var pdf = await request!.ExecuteAsync(_renderer, ct);
var response = req.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("Content-Type", "application/pdf");
await response.Body.WriteAsync(pdf.BinaryData, ct);
return response;
}
Note: Azure Functions Consumption Plan is not supported. Use the Premium Plan (EP1+) or Dedicated (App Service) Plan.
Client examples in other languages
TypeScript / JavaScript
const request = {
url: "https://myapp.com/invoice/42",
paperFormat: "A4",
landscape: false,
metadata: { title: "Invoice #42", author: "Billing System" }
};
const response = await fetch("https://pdf-service/api/pdf", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(request)
});
const blob = await response.blob();
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "invoice.pdf";
a.click();
Python
import requests
payload = {
"url": "https://myapp.com/invoice/42",
"paperFormat": "A4",
"metadata": { "title": "Invoice #42", "author": "Billing System" }
}
response = requests.post("https://pdf-service/api/pdf", json=payload)
response.raise_for_status()
with open("invoice.pdf", "wb") as f:
f.write(response.content)
PdfRequest properties
Source (one required)
| Property | Type | Description |
|---|---|---|
Url |
string? |
URL to render. Mutually exclusive with Html. |
Html |
string? |
Raw HTML to render. Mutually exclusive with Url. |
Layout
| Property | Type | Default | Description |
|---|---|---|---|
Landscape |
bool |
false |
Landscape orientation. |
PaperFormat |
string |
"A4" |
"A4", "A3", "Letter", "Legal", "Tabloid". |
Margins |
PdfRequestMargins? |
null (1 cm) |
Page margins as CSS lengths (e.g. "10mm", "1cm"). |
Grayscale |
bool |
false |
Render in grayscale. |
PrintBackground |
bool |
true |
Include CSS background colours and images. |
MediaType |
string |
"screen" |
CSS media type: "screen" or "print". |
Headers & footers
| Property | Type | Description |
|---|---|---|
Header |
string? |
HTML header template. Supports <span class='pageNumber'>, <span class='totalPages'>, <span class='date'>. |
Footer |
string? |
HTML footer template. Same token support as Header. |
Watermark
| Property | Type | Description |
|---|---|---|
Watermark |
PdfRequestWatermark? |
Overlay applied to every page. |
Wait strategy
| Property | Type | Default | Description |
|---|---|---|---|
WaitStrategy |
string |
"networkIdle" |
When to capture. See values below. |
WaitTimeoutMs |
int |
30000 |
Timeout in ms. |
| Value | Behaviour |
|---|---|
"networkIdle" |
Wait until no network activity for 500 ms (default). |
"signal" |
Wait for window.cobaltNotifyRender() from page JavaScript. |
"selector:#my-id" |
Wait until the CSS selector is present and visible. |
"js:window.ready===true" |
Poll a JavaScript expression until truthy. |
"delay:2000" |
Fixed delay in milliseconds. |
HTTP & authentication
| Property | Type | Default | Description |
|---|---|---|---|
UserAgent |
string? |
null |
Browser User-Agent string. |
ExtraHeaders |
Dictionary<string,string> |
{} |
HTTP headers sent with every request. |
Cookies |
List<PdfRequestCookie> |
[] |
Cookies injected before navigation. |
LocalStorage |
Dictionary<string,string> |
{} |
localStorage values set before load. |
SessionStorage |
Dictionary<string,string> |
{} |
sessionStorage values set before load. |
JavaScript
| Property | Type | Default | Description |
|---|---|---|---|
CustomJs |
string? |
null |
JavaScript executed on the page before capture. |
BypassCsp |
bool |
false |
Bypass Content Security Policy. |
Lazy loading
| Property | Type | Default | Description |
|---|---|---|---|
LazyLoadPages |
int? |
null |
Viewport-heights to scroll to trigger lazy content. |
LazyLoadDelayMs |
int |
200 |
Pause between scroll steps (ms). |
Encryption
| Property | Type | Default | Description |
|---|---|---|---|
Encryption.UserPassword |
string? |
null |
Password required to open the PDF. |
Encryption.OwnerPassword |
string? |
null |
Full-access password. |
Encryption.AllowPrinting |
bool |
true |
Allow printing. |
Encryption.AllowCopying |
bool |
false |
Allow copying text. |
Encryption.AllowModification |
bool |
false |
Allow editing. |
Metadata
| Property | Type | Description |
|---|---|---|
Metadata.Title |
string? |
Document title (shown in PDF reader title bar). |
Metadata.Author |
string? |
Author name. |
Metadata.Subject |
string? |
Document subject. |
Metadata.Keywords |
string? |
Comma-separated keywords. |
Metadata.Creator |
string? |
Application that created the document. |
PdfResponse
Returned by the rendering service after a successful render.
| Property | Type | Description |
|---|---|---|
Data |
string |
Base64-encoded PDF binary. |
SizeBytes |
long |
Size of the PDF in bytes. |
RenderedAt |
DateTime |
UTC timestamp of when the render completed. |
Helpers:
byte[] bytes = response.ToBytes(); // decode to raw bytes
MemoryStream stream = response.ToStream(); // decode to a MemoryStream
Factory (server-side):
var response = PdfResponse.FromBytes(pdf.BinaryData);
Returning the PDF
Your endpoint can respond in two ways:
Raw bytes — application/pdf
Best for browser downloads, mobile apps, and direct file saves.
return Results.File(pdf.BinaryData, "application/pdf", "output.pdf");
JSON — PdfResponse
Best for service-to-service calls where the caller needs to process or store the PDF.
return Results.Ok(PdfResponse.FromBytes(pdf.BinaryData));
Platform summary
| Platform | Server package | Preset | Notes |
|---|---|---|---|
| Azure Functions Premium | CobaltPDF |
ConfigureForAzure |
Do not use Consumption Plan |
| Azure App Service (Linux) | CobaltPDF |
ConfigureForAzure |
Set license in App Settings |
| Azure Container Apps | CobaltPDF |
ConfigureForDocker |
Standard Docker container |
| AWS ECS / Fargate | CobaltPDF |
ConfigureForAwsEcs |
Recommended for sustained load |
| AWS Lambda | CobaltPDF |
ConfigureForLowMemory |
Custom container; pool may restart |
| ASP.NET Core (Docker) | CobaltPDF |
ConfigureForDocker |
Full control, any host |
Security considerations
- Authenticate every endpoint. The rendering service can reach any URL on its network — an unauthenticated endpoint is a security risk.
- Whitelist allowed domains if you don't control all callers, to prevent SSRF.
- Store license keys in secrets — Azure Key Vault, AWS Secrets Manager, or environment variables.
- Do not expose
Htmlrendering publicly without sanitisation — arbitrary HTML can be used to render internal URLs.
Documentation
Full deployment guides (Azure Functions, AWS Lambda, ECS/Fargate), the complete JSON schema, and working server examples are available at:
cobaltpdf.com/docs/articles/cobalt-requests.html
License
See the CobaltPDF website for licensing details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- System.Text.Json (>= 8.0.5)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on CobaltPDF.Requests:
| Package | Downloads |
|---|---|
|
CobaltPDF
A high-performance .NET library for creating pixel-perfect PDFs from HTML and URLs using a managed Chromium browser pool. Supports headers, footers, watermarks (including rasterized), AES-256 encryption, page splitting and merging, metadata, cookies, custom JavaScript, lazy loading, and more. Targets .NET 8.0+ (compatible with .NET 8, 9, and 10). |
|
|
CobaltPDF.WebKit
Headless WebKitGTK-based HTML to PDF renderer for .NET. Drop-in API-compatible with CobaltPDF (the Chromium-based one) - same C# API, same fluent methods, same CobaltEngine type. 96% lower idle memory than Chromium and 57% faster on warm renders. On Linux the library auto-provisions a portable WebKit bundle on first use - no Docker, no apt, no system setup - so the same NuGet works on Azure App Service Linux, Azure Container Apps, AKS, ECS, and any Ubuntu/Alpine container. |
GitHub repositories
This package is not used by any popular GitHub repositories.
v1.6.0
- Added a fluent builder for PdfRequest, mirroring the CobaltEngine fluent API: PdfRequest.ForUrl(url) / PdfRequest.ForHtml(html), chained .WithPaperFormat/.WithMargins/.WithHeader/.WithWatermark/.WithEncryption/.WithMetadata/.AddCookie/... then .Build(). PdfRequest.ToBuilder() adapts an existing instance.
- Purely additive: PdfRequest is unchanged and object-initializer construction works exactly as before. The fluent path produces an identical PdfRequest (and identical JSON).