Gotenberg.Sharp.API.Client
2.8.4
dotnet add package Gotenberg.Sharp.API.Client --version 2.8.4
NuGet\Install-Package Gotenberg.Sharp.API.Client -Version 2.8.4
<PackageReference Include="Gotenberg.Sharp.API.Client" Version="2.8.4" />
<PackageVersion Include="Gotenberg.Sharp.API.Client" Version="2.8.4" />
<PackageReference Include="Gotenberg.Sharp.API.Client" />
paket add Gotenberg.Sharp.API.Client --version 2.8.4
#r "nuget: Gotenberg.Sharp.API.Client, 2.8.4"
#:package Gotenberg.Sharp.API.Client@2.8.4
#addin nuget:?package=Gotenberg.Sharp.API.Client&version=2.8.4
#tool nuget:?package=Gotenberg.Sharp.API.Client&version=2.8.4
<h1> <img src="https://raw.githubusercontent.com/ChangemakerStudios/GotenbergSharpApiClient/refs/heads/develop/resources/gotenberg-sharp-client.png" width="48" height="48" align="top" /> Gotenberg Sharp API Client </h1>
⭐ For Gotenberg v7 & v8 ⭐
.NET C# Client for interacting with the Gotenberg v7 & v8 micro-service's API. Gotenberg is a Docker-powered stateless API for converting & merging HTML, Markdown and Office documents to PDF. The client supports a configurable Polly retry policy with exponential backoff for handling transient exceptions.
Getting Started
Using Docker Run
Pull the image from dockerhub.com
> docker pull gotenberg/gotenberg:latest
Create & start a container
docker run --name gotenbee8x --rm -p 3000:3000 gotenberg/gotenberg:latest gotenberg --api-timeout=1800s --log-level=debug
Using Docker Compose (with Basic Auth)
For local development with basic authentication enabled, use the provided docker-compose file:
docker-compose -f docker/docker-compose-basic-auth.yml up -d
Pre-configured with test credentials:
- Username:
testuser - Password:
testpass
.NET Core Project Setup
Install nuget package into your project
PM> Install-Package Gotenberg.Sharp.Api.Client
Note: Use v1.x nugets for Gotenberg v6.
IntelliSense Documentation
All public APIs include comprehensive XML documentation with clear descriptions, parameter details, and links to official Gotenberg documentation. IntelliSense provides:
- Method descriptions with Gotenberg route documentation links
- Parameter explanations and valid value ranges
- Exception documentation for error handling
- Usage notes and best practices
AppSettings
"GotenbergSharpClient": {
"ServiceUrl": "http://localhost:3000",
"HealthCheckUrl": "http://localhost:3000/health",
"RetryPolicy": {
"Enabled": true,
"RetryCount": 4,
"BackoffPower": 1.5,
"LoggingEnabled": true
}
}
Optional: Basic Authentication
Gotenberg v8+ - If your Gotenberg instance is configured with basic authentication (using --api-enable-basic-auth), you can provide credentials in the settings:
"GotenbergSharpClient": {
"ServiceUrl": "http://localhost:3000",
"HealthCheckUrl": "http://localhost:3000/health",
"BasicAuthUsername": "your-username",
"BasicAuthPassword": "your-password",
"RetryPolicy": {
"Enabled": true,
"RetryCount": 4,
"BackoffPower": 1.5,
"LoggingEnabled": true
}
}
Configure Services In Startup.cs
Basic Configuration (using appsettings.json)
public void ConfigureServices(IServiceCollection services)
{
.....
services.AddOptions<GotenbergSharpClientOptions>()
.Bind(Configuration.GetSection(nameof(GotenbergSharpClient)));
services.AddGotenbergSharpClient();
.....
}
Programmatic Configuration
public void ConfigureServices(IServiceCollection services)
{
.....
// Configure with an action
services.AddOptions<GotenbergSharpClientOptions>()
.Configure(options =>
{
options.ServiceUrl = new Uri("http://localhost:3000");
options.TimeOut = TimeSpan.FromMinutes(5);
options.BasicAuthUsername = "username";
options.BasicAuthPassword = "password";
// Configure retry policy
options.RetryPolicy = new RetryOptions
{
Enabled = true,
RetryCount = 4,
BackoffPower = 1.5,
LoggingEnabled = true
};
});
services.AddGotenbergSharpClient();
.....
}
Hybrid Configuration (appsettings + programmatic override)
public void ConfigureServices(IServiceCollection services)
{
.....
services.AddOptions<GotenbergSharpClientOptions>()
.Bind(Configuration.GetSection(nameof(GotenbergSharpClient)))
.PostConfigure(options =>
{
// Override or add settings programmatically (runs after binding)
options.TimeOut = TimeSpan.FromMinutes(10); // Override timeout
options.BasicAuthUsername = Environment.GetEnvironmentVariable("GOTENBERG_USER");
options.BasicAuthPassword = Environment.GetEnvironmentVariable("GOTENBERG_PASS");
});
services.AddGotenbergSharpClient();
.....
}
Using GotenbergSharpClient
See the examples folder for complete working examples as console applications.
Required Using Statements
using Gotenberg.Sharp.API.Client;
using Gotenberg.Sharp.API.Client.Domain.Builders;
using Gotenberg.Sharp.API.Client.Domain.Builders.Faceted;
using Gotenberg.Sharp.API.Client.Domain.Requests.Facets; // For Cookie, etc.
Html To Pdf
With embedded assets:
[HttpGet]
public async Task<ActionResult> HtmlToPdf([FromServices] GotenbergSharpClient sharpClient)
{
var builder = new HtmlRequestBuilder()
.AddDocument(doc =>
doc.SetBody(GetBody()).SetFooter(GetFooter())
).WithPageProperties(pp =>
{
pp.SetPaperSize(PaperSizes.A3)
.SetMargins(Margins.None)
.SetScale(.99);
}).WithAsyncAssets(async assets => assets.AddItem("some-image.jpg", await GetImageBytes()));
var req = await builder.BuildAsync();
var result = await sharpClient.HtmlToPdfAsync(req);
return this.File(result, "application/pdf", "gotenbergFromHtml.pdf");
}
Url To Pdf
Url to Pdf with custom page range, header & footer:
public async Task<Stream> CreateFromUrl(string headerPath, string footerPath)
{
var builder = new UrlRequestBuilder()
.SetUrl("https://www.cnn.com")
.ConfigureRequest(config =>
{
config.SetPageRanges("1-2");
})
.AddAsyncHeaderFooter(async
doc => doc.SetHeader(await File.ReadAllTextAsync(headerPath))
.SetFooter(await File.ReadAllBytesAsync(footerPath)
)).WithPageProperties(pp =>
{
pp.SetPaperSize(PaperSizes.A4)
.SetMargins(Margins.None)
.SetScale(.90)
.SetLandscape();
});
var request = await builder.BuildAsync();
return await _sharpClient.UrlToPdfAsync(request);
}
Merge Office Docs
Merges office documents:
public async Task<Stream> DoOfficeMerge(string sourceDirectory)
{
var builder = new MergeOfficeBuilder()
.WithAsyncAssets(async a => a.AddItems(await GetDocsAsync(sourceDirectory)))
.SetPdfFormat(LibrePdfFormats.A2b);
var request = await builder.BuildAsync();
return await _sharpClient.MergeOfficeDocsAsync(request);
}
Markdown to Pdf
Markdown to Pdf conversion with embedded assets:
public async Task<Stream> CreateFromMarkdown()
{
var builder = new HtmlRequestBuilder()
.AddAsyncDocument(async
doc => doc.SetHeader(await this.GetHeaderAsync())
.SetBody(await GetBodyAsync())
.SetContainsMarkdown()
.SetFooter(await GetFooterAsync())
).WithPageProperties(pp =>
{
pp.UseChromeDefaults().SetLandscape().SetScale(.90);
}).WithAsyncAssets(async
a => a.AddItems(await GetMarkdownAssets())
);
var request = await builder.BuildAsync();
return await _sharpClient.HtmlToPdfAsync(request);
}
Working with Cookies
Add cookies to the Chromium cookie jar for authenticated requests (v2.8.1+):
public async Task<Stream> CreatePdfWithCookies()
{
var builder = new UrlRequestBuilder()
.SetUrl("https://example.com/protected")
.SetConversionBehaviors(b =>
{
b.AddCookie(new Cookie
{
Name = "session_token",
Value = "abc123xyz",
Domain = "example.com",
Path = "/",
Secure = true,
HttpOnly = true,
SameSite = "Lax"
});
})
.WithPageProperties(pp => pp.UseChromeDefaults());
var request = await builder.BuildAsync();
return await _sharpClient.UrlToPdfAsync(request);
}
Document Metadata
Add custom metadata to your PDFs (v2.6+):
public async Task<Stream> CreatePdfWithMetadata()
{
var builder = new HtmlRequestBuilder()
.AddDocument(doc => doc.SetBody("<html><body><h1>Document with Metadata</h1></body></html>"))
.SetConversionBehaviors(b =>
{
b.SetMetadata(new Dictionary<string, object>
{
{ "Author", "John Doe" },
{ "Title", "My Document" },
{ "Subject", "Important Report" },
{ "Keywords", "report, pdf, gotenberg" }
});
})
.WithPageProperties(pp => pp.UseChromeDefaults());
var request = await builder.BuildAsync();
return await _sharpClient.HtmlToPdfAsync(request);
}
PDF Format Conversion
Convert PDFs to PDF/A formats (v2.8+):
public async Task<Stream> ConvertToPdfA(string pdfPath)
{
var builder = new PdfConversionBuilder()
.WithPdfs(b => b.AddItem("document.pdf", File.ReadAllBytes(pdfPath)))
.SetPdfFormat(LibrePdfFormats.A2b);
var request = await builder.BuildAsync();
return await _sharpClient.ConvertPdfDocumentsAsync(request);
}
Single Page Output
Generate a single-page PDF from multi-page content (v2.8.1+):
public async Task<Stream> CreateSinglePagePdf()
{
var builder = new UrlRequestBuilder()
.SetUrl("https://www.example.com")
.WithPageProperties(pp =>
{
pp.UseChromeDefaults()
.SetSinglePage(true);
});
var request = await builder.BuildAsync();
return await _sharpClient.UrlToPdfAsync(request);
}
Webhook
All request types support webhooks
public async Task SendUrlToWebhookEndpoint(string headerPath, string footerPath)
{
var builder = new UrlRequestBuilder()
.SetUrl("https://www.cnn.com")
.ConfigureRequest(reqBuilder =>
{
reqBuilder.AddWebhook(hook =>
{
hook.SetUrl("http://host.docker.internal:5000/api/your/webhookReceiver")
.SetErrorUrl("http://host.docker.internal:5000/api/your/webhookReceiver/error")
.AddExtraHeader("custom-header", "value");
})
.SetPageRanges("1-2");
})
.AddAsyncHeaderFooter(async
b => b.SetHeader(await System.IO.File.ReadAllTextAsync(headerPath))
.SetFooter(await System.IO.File.ReadAllBytesAsync(footerPath))
).WithPageProperties(pp =>
{
pp.SetPaperSize(PaperSizes.A4)
.SetMargins(Margins.None)
.SetScale(.90)
.SetLandscape();
});
var request = await builder.BuildAsync();
await _sharpClient.FireWebhookAndForgetAsync(request);
}
Merge 15 Urls to one pdf
Builds a 30 page pdf by merging the front two pages of 15 news sites. Takes about a minute to complete
public async Task<Stream> CreateWorldNewsSummary()
{
var sites = new[]
{
"https://www.nytimes.com", "https://www.axios.com/", "https://www.csmonitor.com",
"https://www.wsj.com", "https://www.usatoday.com", "https://www.irishtimes.com",
"https://www.lemonde.fr", "https://calgaryherald.com", "https://www.bbc.com/news/uk",
"https://www.thehindu.com", "https://www.theaustralian.com.au",
"https://www.welt.de", "https://www.cankaoxiaoxi.com",
"https://www.novinky.cz", "https://www.elobservador.com.uy"
}
.Select(u => new Uri(u));
var builders = CreateBuilders(sites);
var requests = builders.Select(b => b.Build());
return await ExecuteRequestsAndMerge(requests);
}
IEnumerable<UrlRequestBuilder> CreateBuilders(IEnumerable<Uri> uris)
{
foreach (var uri in uris)
{
yield return new UrlRequestBuilder()
.SetUrl(uri)
.ConfigureRequest(req => { req.SetPageRanges("1-2"); })
.AddHeaderFooter(docBuilder =>
{
docBuilder.SetHeader(GetHeadFoot(uri.Host.Replace("www.", string.Empty).ToUpper()))
.SetFooter(GetHeadFoot(uri.ToString()));
})
.WithPageProperties(pp =>
{
pp.UseChromeDefaults()
.SetScale(.90)
.SetLandscape()
.SetMarginLeft(.5)
.SetMarginRight(.5);
});
}
static string GetHeadFoot(string heading)
=> "<html><head> <style> body { font-size: 8rem; } h1 { margin-left: auto; margin-right: auto; } </style></head><body><h1>" +
heading + "</h1></body></html>";
}
async Task<Stream> ExecuteRequestsAndMerge(IEnumerable<UrlRequest> requests)
{
var tasks = requests.Select(r => _sharpClient.UrlToPdfAsync(r));
var results = await Task.WhenAll(tasks);
var mergeBuilder = new MergeBuilder()
.WithAssets(b => {
b.AddItems(results.Select((r, i) => KeyValuePair.Create($"{i}.pdf", r)));
});
var request = mergeBuilder.Build();
return await _sharpClient.MergePdfsAsync(request);
}
Advanced Features
PDF/UA Support for HTML Conversions
Enable Universal Access for accessible PDFs from HTML (v2.4+):
public async Task<Stream> CreateAccessiblePdf()
{
var builder = new HtmlRequestBuilder()
.AddDocument(doc => doc.SetBody("<html><body><h1>Accessible Document</h1></body></html>"))
.SetConversionBehaviors(b => b.SetPdfUa(true))
.WithPageProperties(pp => pp.UseChromeDefaults());
var request = await builder.BuildAsync();
return await _sharpClient.HtmlToPdfAsync(request);
}
PDF/UA for PDF Conversions
Enable Universal Access when converting PDFs to PDF/A (v2.4+):
public async Task<Stream> ConvertToAccessiblePdfA(string pdfPath)
{
var builder = new PdfConversionBuilder()
.WithPdfs(b => b.AddItem("document.pdf", File.ReadAllBytes(pdfPath)))
.SetPdfFormat(LibrePdfFormats.A2b)
.EnablePdfUa(true);
var request = await builder.BuildAsync();
return await _sharpClient.ConvertPdfDocumentsAsync(request);
}
Flatten PDFs
Flatten PDF forms and annotations (v2.8+):
public async Task<Stream> FlattenPdf(string pdfPath)
{
var builder = new PdfConversionBuilder()
.WithPdfs(b => b.AddItem("form.pdf", File.ReadAllBytes(pdfPath)))
.EnableFlatten(true);
var request = await builder.BuildAsync();
return await _sharpClient.ConvertPdfDocumentsAsync(request);
}
Skip Network Idle Event
Speed up conversions by skipping network idle wait (Gotenberg v8+ only):
public async Task<Stream> FastConversion()
{
var builder = new UrlRequestBuilder()
.SetUrl("https://example.com")
.SetConversionBehaviors(b => b.SkipNetworkIdleEvent())
.WithPageProperties(pp => pp.UseChromeDefaults());
var request = await builder.BuildAsync();
return await _sharpClient.UrlToPdfAsync(request);
}
Custom Page Properties
Fine-tune page dimensions and properties:
public async Task<Stream> CustomPageProperties()
{
var builder = new HtmlRequestBuilder()
.AddDocument(doc => doc.SetBody("<html><body><h1>Custom Page</h1></body></html>"))
.WithPageProperties(pp =>
{
pp.SetPaperSize(PaperSizes.Letter)
.SetMargins(Margins.Normal)
.SetScale(0.95)
.SetLandscape()
.SetPrintBackground(true)
.SetGenerateDocumentOutline(true)
.SetOmitBackground(false);
});
var request = await builder.BuildAsync();
return await _sharpClient.HtmlToPdfAsync(request);
}
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 is compatible. net5.0-windows was computed. net6.0 is compatible. 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 is compatible. 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 is compatible. 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 is compatible. |
| .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
- Microsoft.Bcl.HashCode (>= 1.1.1)
- Microsoft.Extensions.DependencyInjection (>= 2.2.0)
- Microsoft.Extensions.Http (>= 2.2.0)
- Microsoft.Extensions.Http.Polly (>= 2.2.0)
- MimeMapping (>= 3.0.1)
- Newtonsoft.Json (>= 13.0.3)
-
.NETStandard 2.1
- Microsoft.Extensions.DependencyInjection (>= 3.1.5)
- Microsoft.Extensions.Http (>= 3.1.5)
- Microsoft.Extensions.Http.Polly (>= 3.1.5)
- MimeMapping (>= 3.0.1)
- Newtonsoft.Json (>= 13.0.3)
-
net5.0
- Microsoft.Extensions.DependencyInjection (>= 5.0.0)
- Microsoft.Extensions.Http (>= 5.0.0)
- Microsoft.Extensions.Http.Polly (>= 5.0.0)
- MimeMapping (>= 3.0.1)
- Newtonsoft.Json (>= 13.0.3)
-
net6.0
- Microsoft.Extensions.DependencyInjection (>= 6.0.0)
- Microsoft.Extensions.Http (>= 6.0.0)
- Microsoft.Extensions.Http.Polly (>= 6.0.0)
- MimeMapping (>= 3.0.1)
- Newtonsoft.Json (>= 13.0.3)
-
net7.0
- Microsoft.Extensions.DependencyInjection (>= 7.0.0)
- Microsoft.Extensions.Http (>= 7.0.0)
- Microsoft.Extensions.Http.Polly (>= 7.0.0)
- MimeMapping (>= 3.0.1)
- Newtonsoft.Json (>= 13.0.3)
-
net8.0
- Microsoft.Extensions.DependencyInjection (>= 8.0.0)
- Microsoft.Extensions.Http (>= 8.0.0)
- Microsoft.Extensions.Http.Polly (>= 8.0.7)
- MimeMapping (>= 3.0.1)
- Newtonsoft.Json (>= 13.0.3)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Gotenberg.Sharp.API.Client:
| Package | Downloads |
|---|---|
|
SpCraft.Net.Common.Pdf
Package Description |
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 2.8.4 | 1,265 | 10/18/2025 |
| 2.8.3 | 4,312 | 10/6/2025 |
| 2.8.1 | 217 | 10/5/2025 |
| 2.8.0 | 143,120 | 3/25/2025 |
| 2.5.0 | 30,053 | 2/7/2025 |
| 2.4.0 | 178,168 | 8/10/2024 |
| 2.3.0 | 108,484 | 4/17/2024 |
| 2.2.2 | 54,379 | 1/30/2024 |
| 2.1.1 | 302,314 | 10/1/2022 |
| 2.0.2 | 59,306 | 8/30/2022 |
| 2.0.1 | 1,409 | 8/30/2022 |
| 2.0.0-alpha0002 | 35,359 | 3/3/2022 |
| 1.2.0 | 109,051 | 5/11/2021 |
| 1.0.0 | 134,059 | 6/3/2020 |
| 0.9.51 | 110,469 | 3/22/2020 |
| 0.9.37 | 28,181 | 2/11/2020 |
| 0.9.26 | 2,196 | 12/19/2019 |
| 0.9.2 | 7,225 | 11/21/2019 |
v2.8.4 - Fixed hybrid configuration for basic authentication credentials. See CHANGES.MD for full details.
v2.8.3 - Added programmatic configuration support. Comprehensive documentation improvements. Fixed NuGet packaging issues. See CHANGES.MD for full details.
v2.8.1 - Added strongly-typed cookie support. Added basic authentication support. Added SinglePage page property. Fixed margins bug. Project restructure (moved /lib to /src).
v2.8 - Improving handling of PDF formatting and added flatten support.
v2.7 - Fixes issue with "Inches".
v2.6 - Updated office Extensions. Added document metadata support. Add Dimension.FromUnit() support for dimensional values.
v2.5 - Renamed "Dimentions" to "PageProperties". Added support for 'GenerateDocumentOutline' and 'OmitBackground.'
v2.4 - Updated dependencies. Removed Annotations. Add support for PDF/UA form field. Thank you for the PR @lennartb-!
v2.3 - Added Convert Page 'ExportFormFields' flag support (Gotenberg v8.3+ Only). Added .NET 8 target.
v2.2 - Added 'SkipNetworkIdle' flag support (Gotenberg v8+ Only). Thank you for the PR @guillaumeduhr! Upgraded nugets to latest. Added .NET 7.0 support.
v2.1 - Added Trace Support. Fixed extra webhook header support.
v2.0 - Upgraded to support Gotenberg v7 -- this version no longer works with Gotenberg v6.