You're Invited:Meet the Socket Team at BlackHat and DEF CON in Las Vegas, Aug 4-6.RSVP
Socket
Book a DemoInstallSign in
Socket

Gotenberg.Sharp.API.Client.Framsikt

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

Gotenberg.Sharp.API.Client.Framsikt

C# API client for interacting with the Gotenberg v7 & v8 micro-service's API, 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 back-off for handling transient exceptions.

3.0.0
Source
nugetNuGet
Version published
Maintainers
1
Created
Source

gotenberg icon Gotenberg.Sharp.Api.Client

NuGet version Downloads Build status

⭐ 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

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

.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.

AppSettings

  "GotenbergSharpClient": {
    "ServiceUrl": "http://localhost:3000",
    "HealthCheckUrl": "http://localhost:3000/health",
    "RetryPolicy": {
      "Enabled": true,
      "RetryCount": 4,
      "BackoffPower": 1.5,
      "LoggingEnabled": true
    }
  }

Configure Services In Startup.cs

public void ConfigureServices(IServiceCollection services)
{
	.....
    services.AddOptions<GotenbergSharpClientOptions>()
	        .Bind(Configuration.GetSection(nameof(GotenbergSharpClient)));
    services.AddGotenbergSharpClient();
	.....    
}

Using GotenbergSharpClient

See the linqPad folder for complete examples.

New v7+ API Features

Screenshots

  • Formats: PNG, JPEG, WebP with configurable quality and transparency
  • Sources: Capture from URLs, HTML files, or Markdown content
  • Options: Device dimensions, clip regions, background control
  • Examples: UrlScreenshot.linq, HtmlScreenshot.linq

HTML Rendering

  • Purpose: Extract fully-rendered HTML after JavaScript execution
  • Sources: URLs, HTML files, or Markdown content
  • Use Cases: Web scraping, SEO analysis, content processing
  • Examples: UrlHtmlRendering.linq, HtmlFileRendering.linq

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);
}

Screenshot Capture

Capture screenshots from URLs or HTML content:

URL to Screenshot

public async Task<Stream> CreateUrlScreenshot()
{
    var builder = new UrlScreenshotRequestBuilder()
        .SetUrl("https://www.example.com")
        .SetScreenshotBehaviors(b =>
        {
            b.SetDimensions(1920, 1080)
             .SetFormat(ScreenshotImageFormat.Png)
             .SetClip(true)
             .SetOmitBackground(false);
        })
        .SetConversionBehaviors(b =>
        {
            b.EmulateAsScreen()
             .AddAdditionalHeaders("User-Agent", "GotenbergScreenshotBot/1.0");
        });

    var request = await builder.BuildAsync();
    return await _sharpClient.UrlToScreenshotAsync(request);
}

HTML to Screenshot

public async Task<Stream> CreateHtmlScreenshot()
{
    var builder = new HtmlScreenshotRequestBuilder()
        .AddAsyncDocument(async doc =>
            doc.SetBody(await GetHtmlContentAsync())
        )
        .SetScreenshotBehaviors(b =>
        {
            b.SetDimensions(1200, 800)
             .SetFormat(ScreenshotImageFormat.Jpeg)
             .SetQuality(90)
             .SetOptimizeForSpeed(true);
        })
        .WithAsyncAssets(async assets =>
            assets.AddItems(await GetAssetFilesAsync())
        );

    var request = await builder.BuildAsync();
    return await _sharpClient.HtmlToScreenshotAsync(request);
}

HTML Rendering

Capture fully-rendered HTML after JavaScript execution:

URL to HTML

public async Task<Stream> RenderUrlToHtml()
{
    var builder = new UrlHtmlRenderingRequestBuilder()
        .SetUrl("https://jsonplaceholder.typicode.com/posts/1")
        .SetConversionBehaviors(b =>
        {
            b.EmulateAsScreen()
             .SetBrowserWaitDelay(2) // Wait for dynamic content
             .AddAdditionalHeaders("Accept", "application/json,text/html,*/*");
        });

    var request = await builder.BuildAsync();
    return await _sharpClient.UrlToHtmlAsync(request);
}

HTML/Markdown to HTML

public async Task<Stream> RenderMarkdownToHtml()
{
    var builder = new HtmlFileRenderingRequestBuilder(containsMarkdown: true)
        .AddDocument(doc =>
            doc.SetBody("# Dynamic Content\n\nThis **markdown** will be rendered.")
               .SetContainsMarkdown(true)
        )
        .WithAssets(assets =>
        {
            assets.AddItem("styles.css", "body { font-family: Arial; }");
        })
        .SetConversionBehaviors(b =>
        {
            b.EmulateAsScreen()
             .SetBrowserWaitExpression("document.readyState === 'complete'");
        });

    var request = await builder.BuildAsync();
    return await _sharpClient.HtmlFileToHtmlAsync(request);
}

Merge Office Docs

Merges office documents and configures the request time-out:

public async Task<Stream> DoOfficeMerge(string sourceDirectory)
{
	var builder = new MergeOfficeBuilder()
		.WithAsyncAssets(async a => a.AddItems(await GetDocsAsync(sourceDirectory)));

	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);
}

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);
}

Keywords

Gotenberg

FAQs

Package last updated on 21 Jul 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts