v1.6.4
Fixed
  • Render latency on network-restricted hosts. Renders that took 16–45 s on servers with restricted outbound network access (hanging font/analytics/CDN requests that never reach network idle) no longer burn hard-coded internal waits. When an explicit wait strategy is configured (ForDelay, ForSelector, ForJavaScript, ForSignal), the fixed 5 s client-side redirect probe on URL renders and the fixed 10 s network-idle wait before custom JS are now skipped entirely — the strategy already defines page readiness.
  • Browser pool no longer discards warm browsers under concurrent load. Previously, healthy browsers were disposed whenever the pool held more than MinSize, so every concurrent render beyond the first launched a cold Chromium and threw it away — typically adding several seconds per render on Windows Server, where antivirus scans each launch. Healthy browsers are now recycled up to MaxSize and kept warm; a background reaper reclaims browsers idle longer than PoolOptions.IdleShrinkAfter (default 60 s), never shrinking below MinSize.
Added
  • WithNetworkIdleTimeout(TimeSpan) (and PdfOptions.NetworkIdleTimeout) — caps all internal network-idle waits: the pre-custom-JS wait, the lazy-load scroll waits, and the default network-idle wait strategy (previously an implicit 30 s, now explicit and configurable). TimeSpan.Zero skips them entirely.
  • WithClientRedirectWait(TimeSpan) / WithoutClientRedirectWait() (and PdfOptions.ClientRedirectTimeout) — explicit control over the client-side redirect probe on URL renders, overriding the automatic skip in either direction.
  • PoolOptions.IdleShrinkAfter (default 60 s) — how long a warm browser may sit idle before the pool reclaims it. TimeSpan.Zero restores the previous dispose-on-return behavior for memory-critical hosts.
  • Per-stage timing diagnostics. Every render now logs stage durations (acquire pooled browser, navigate, client-redirect probe, custom JS, wait strategy, lazy-load scroll, pdf capture, total render) as [Browser TIMING] entries through the existing CobaltEngine.LoggingMode / OnBrowserLog pipeline — zero overhead when logging is disabled, so support cases can pinpoint the slow stage immediately.
Compatibility
  • Behavioral change: with an explicit wait strategy configured, the 5 s redirect probe and the 10 s pre-custom-JS idle wait no longer run. Callers that relied on those implicit waits alongside an explicit strategy can re-enable them via WithClientRedirectWait(...) / WithNetworkIdleTimeout(...).
  • Behavioral change: after a burst of concurrent renders, the pool now holds up to MaxSize browsers warm for up to IdleShrinkAfter — higher steady-state memory for up to 60 s. Set IdleShrinkAfter = TimeSpan.Zero for the old behavior.
  • Default-configuration single renders (no custom JS, default wait strategy) behave identically to 1.6.3. No public API was removed — all changes are additive options and methods.
v1.6.3
Added
  • WithSkipTrailingBlankPage() (and PdfOptions.SkipTrailingBlankPage, plus PdfRequest.SkipTrailingBlankPage via CobaltPDF.Requests 1.6.2) — suppresses the trailing blank page produced when the document's last element carries page-break-after: always, a common pattern when generating pages in a loop. Opt-in; default output is unchanged.
Security
  • Dependency security update. Magick.NET-Q8-AnyCPU moves to 14.16.0, clearing the ImageMagick advisories reported against 14.14.0 (used internally to recompress images during post-processing). Microsoft.Extensions.DependencyInjection and System.Formats.Asn1 move to 10.0.11. dotnet list package --vulnerable now reports no vulnerable packages; rendering behaviour is unchanged.
Changed
  • Output PDFs now identify as CobaltPDF. /Producer no longer leaks the internal post-processing library ("PDFsharp … (Original: Skia/PDF …)") and /Creator no longer leaks the headless browser User-Agent — in the doc-info, the XMP packet, and the trailer comment. A Producer/Creator supplied via WithMetadata still wins. Raw output via WithCompression(false) without metadata remains byte-for-byte untouched, and encrypted documents keep the previous strings.
  • Friendlier licensing errors. Specific failures (invalid signature, expired license, ended support period, revoked key) now surface their actionable message directly instead of a generic "License validation failed."; the generic wrapper (malformed keys) now explains the likely cause and notes that evaluation needs no key.
  • CobaltPDF.Requests dependency updated to v1.6.2.
v1.6.2
Fixed
  • Azure preset no longer breaks multi-page PDFs. CloudEnvironment.ConfigureForAzure (and ConfigureForLowMemory) no longer add --single-process — that flag crashes the Chromium renderer on multi-page or non-trivial documents (only trivial single-page renders survived it). 1.6.1 could fail real renders on Azure when these presets were used, so upgrading from 1.6.1 is recommended. The presets now use the stable multi-process model.
Changed
  • The bundled Linux dependencies (added in 1.6.1) now activate only when the host is missing Chromium's graphics stack, so Linux hosts that already provide the libraries render exactly as before.
v1.6.1
Added
  • Runs on stock Linux with no container. The package now ships Chromium's OS-level dependencies (system libraries, NSS modules, and base fonts) and points the browser's loader at them automatically on Linux — so the Chromium edition runs on a stock Azure Functions Linux plan or a slim container with a plain code deploy (no custom container, no apt). On Linux hosts that already provide the libraries, nothing changes: the host's own libraries and fonts are used exactly as before, and the bundled set is used only when the host is missing them.
  • CobaltPDF.Requests dependency pinned to v1.6.1.
v1.6.0
Added
  • WithCompression(bool) — output PDFs now re-encode embedded images to shrink the file (typically several times smaller on image-heavy pages). Call WithCompression(false) for raw, lossless output. Powered by Magick.NET (Apache-2.0).
  • WithViewportSize(width[, height]) — sets the render viewport; a tall height triggers IntersectionObserver lazy images without scrolling.
  • WithEagerImages() — forces lazy-loaded images to load before rendering, additionally promoting the JavaScript data-src/data-srcset convention the print path cannot.
  • Pool backpressure & metrics. New PoolOptions.MaxQueueDepth + PoolBusyException let a saturated pool fast-fail extra requests so the host can return HTTP 503 instead of a slow timeout (default 0 = unbounded). New CobaltEngine.GetPoolStatistics() / CobaltPoolStatistics expose live pool gauges and lifetime counters for health endpoints.
Changed
  • Desktop-layout rendering by default. Renders now capture the full desktop layout (≈1280 px wide) scaled to fit the page — instead of reflowing to the narrow print width. The paper keeps its true size (e.g. A4). Set WithMediaType(CssMediaType.Print) to restore the old Chrome-print reflow.
  • Image compression is on by default (see above), so output is now slightly lossy unless you call WithCompression(false).
  • Default User-Agent is now a desktop Chrome UA (via PdfOptions.DefaultUserAgent) so UA-sensitive sites serve consistent desktop markup. Override with WithUserAgent(...).
  • Auto-sized concurrency. PoolOptions.MaxSize now defaults to a host-aware value — the smaller of the vCPU count and what fits in ~75% of detected memory, clamped 1–8 — instead of a fixed 5, so it stays safe on memory-constrained hosts. Always overridable.
  • CobaltPDF.Requests dependency updated to v1.6.1.
Deprecated
  • WithoutPostProcessing() — use WithCompression(bool) instead (WithoutPostProcessing() is equivalent to WithCompression(false)). It still compiles, and is no longer a no-op on this edition.
Compatibility
  • No public API was removed; existing code compiles and runs unchanged. The default output now differs (desktop-scaled layout + image compression) — combine WithMediaType(CssMediaType.Print) and WithCompression(false) to reproduce v1.5.x output.
v1.5.0
Added
  • PDF page splitting, extraction & merging. New PdfDocument members: PageCount, ExtractPage(int), ExtractPages(start, end), ExtractPages(IEnumerable<int>), SplitIntoPages(), and static FromFile(path), FromBytes(data), and Merge(params PdfDocument[]). Works on any PDF — freshly rendered or loaded from disk — on any OS. Page indices are 0-based; out-of-range indices throw ArgumentOutOfRangeException.
  • Watermark rasterization. New opt-in WatermarkOptions.Rasterize flag (fluent .WithRasterize()) flattens a watermark into a high-resolution image baked into every page — no selectable text and no separate deletable object in a PDF editor. Tamper-resistance for confidential documents; default behaviour is unchanged.
  • WithoutPostProcessing() added as an accepted no-op. Chromium's PDF backend already subsets fonts and compresses images natively, so the method has no effect here.
Security
  • Encryption upgraded to AES-256 (security handler V5/R6, previously AES-128). The WithEncryption(...) API, PdfEncryptionOptions, and all password/permission behaviour are unchanged — only the cipher strength improved. Both CobaltPDF libraries now produce identical AES-256 protection from identical options.
Changed
  • CobaltPDF.Requests dependency updated to v1.5.0 — a serialized PdfRequest can now request a rasterized watermark and carry the new SkipPostProcessing flag.
  • Deployment documentation corrected and expanded after validation on real Azure infrastructure: Linux Azure Functions require a custom container for Chromium (the stock image lacks its system libraries) — the Azure Functions guide and docs now carry validated container walkthroughs and engine toggles.
Compatibility
  • Fully backward compatible — no public API was renamed or removed, and existing code compiles and runs unchanged.
v1.4.1
Added
  • WithUserAgent, WithHttpHeader, and WithHttpHeaders are now declared on the IPdfGenerator and IPdfGeneratorFinal interfaces (previously only available on CobaltEngine), so code holding an interface reference gets the same methods via IntelliSense.
Fixed
  • AddCookie(name, value) without an explicit domain no longer throws "Invalid cookie fields" when the final URL is localhost, an IPv4/IPv6 address, or a single-label intranet hostname. The cookie is now correctly registered as a standard host-only cookie. Cookie inference for public domains is unchanged.
v1.4.0
Security
  • Updated bundled Chromium from 2026.2.1 to 2026.5.16, addressing upstream security advisories.
Removed
  • Dropped the net6.0 target. The package now targets net8.0 (compatible with .NET 8, 9, and 10). Consumers on .NET 6 should stay on v1.3.0 or upgrade their runtime — .NET 6 reached end of Microsoft support in November 2024.
Changed
  • Bumped Microsoft.Extensions.DependencyInjection from 10.0.3 to 10.0.8.
  • Bumped System.Formats.Asn1 from 10.0.3 to 10.0.8.
  • Bumped Microsoft.Playwright from 1.58.0 to 1.60.0.
v1.3.0
Added
  • Multi-target support: the package now ships builds for both net6.0 and net8.0, broadening compatibility with projects on .NET 6, 7, 8, 9, and 10.
Changed
  • CobaltPDF.Requests dependency updated to v1.3.0 (now targets netstandard2.0).
v1.2.2
Fixed
  • Fixed Chromium default header/footer appearing when only one template is provided.
  • Fixed WithLazyLoadPages not working when combined with WithCustomJS or WithWaitStrategy.
Changed
  • WithCustomJS now waits for the page to be fully loaded before executing, so dynamically-injected elements (e.g. cookie consent buttons) are available.
  • Client-side redirects (e.g. bbc.com → bbc.co.uk) are now detected before cookies, custom JS, and wait strategies run.
v1.2.0
Changed
  • Renamed .Landscape() to .WithLandscape() for fluent API consistency.
  • Renamed .UseGrayscale() to .WithGrayscale() for fluent API consistency.
  • Renamed .EmulateMediaType() to .WithMediaType() — shorter and consistent with the With* convention.
  • Renamed .WaitFor() to .WithWaitStrategy() to avoid confusion with async operations.
  • Renamed .ReloadAfterStorageSet() to .WithReloadAfterStorage() for fluent API consistency.
  • Renamed .ConfigureFonts() to .WithFonts() — shorter and consistent with the With* convention.
v1.1.0
Added
  • Fluent .WithWatermark() API for text and HTML watermarks with configurable opacity, rotation, and position.
  • PDF metadata support — set title, author, subject, keywords, and creator via .WithMetadata().
  • CloudEnvironment.ConfigureForAzure preset for Azure App Service and Container Apps deployments.
  • New .ScrollPage() option to trigger lazy-loaded images before capture.
Changed
  • Default pool MaxSize increased from 4 to 8 for better throughput on multi-core hosts.
  • Improved browser recycling logic — instances are now recycled after 50 renders (previously 100).
Fixed
  • Resolved rare deadlock when calling RenderUrlAsPdfAsync with a CancellationToken that fires during navigation.
  • Fixed header/footer templates not respecting @media print styles.
v1.0.1
Fixed
  • Fixed PreWarmAsync() throwing ObjectDisposedException when called immediately after Configure() on Linux containers.
  • Corrected paper size calculation for custom dimensions specified in millimetres.
  • Resolved an issue where AddCookie() cookies were not sent on the initial page load when using RenderUrlAsPdfAsync.
v1.0.0
Added
  • Initial release of CobaltPDF — a high-performance HTML-to-PDF rendering engine for .NET.
  • Chromium-powered rendering with full support for modern CSS (Grid, Flexbox, custom properties, animations).
  • Managed browser pool with configurable MinSize, MaxSize, and automatic recycling.
  • Fluent API for PDF generation — chain options and call a single terminal method.
  • Thread-safe singleton design with isolated browser contexts per render.
  • Cookie, localStorage, and sessionStorage injection per render.
  • Custom HTTP headers and User-Agent per render.
  • Header and footer HTML templates with page number, total pages, and date tokens.
  • PDF encryption with user/owner passwords and granular permission control.
  • Wait strategies: network idle, DOM selector, JavaScript expression, custom signal, fixed delay.
  • Custom JavaScript execution before capture with cobaltNotifyRender() signal support.
  • Cloud environment presets: Docker, AWS ECS, Low-Memory.
  • ASP.NET Core dependency injection via services.AddCobaltPdf().
  • Companion package CobaltPDF.Requests for lightweight microservice clients.