Soenneker.Html.Normalizer
4.0.43
Prefix Reserved
dotnet add package Soenneker.Html.Normalizer --version 4.0.43
NuGet\Install-Package Soenneker.Html.Normalizer -Version 4.0.43
<PackageReference Include="Soenneker.Html.Normalizer" Version="4.0.43" />
<PackageVersion Include="Soenneker.Html.Normalizer" Version="4.0.43" />
<PackageReference Include="Soenneker.Html.Normalizer" />
paket add Soenneker.Html.Normalizer --version 4.0.43
#r "nuget: Soenneker.Html.Normalizer, 4.0.43"
#:package Soenneker.Html.Normalizer@4.0.43
#addin nuget:?package=Soenneker.Html.Normalizer&version=4.0.43
#tool nuget:?package=Soenneker.Html.Normalizer&version=4.0.43
Soenneker.Html.Normalizer
Deterministic, configurable HTML normalization for hashing and change detection.
Installation
dotnet add package Soenneker.Html.Normalizer
```bash
## Usage
```csharp
using Soenneker.Html.Normalizer.Models;
HtmlNormalizationResult result = await normalizer.NormalizeAndHash(renderedHtml);
Console.WriteLine(result.Html);
Console.WriteLine(result.Hash);
The default profile removes common runtime artifacts while preserving indexable content:
- HTML comments
<style>elements- scripts other than
application/ld+json nonceattributes- Blazor
_bl_*element-reference attributes - element IDs and common HTML/ARIA attributes that reference them
- formatting-only inter-element whitespace
It also normalizes line endings and sorts ordinary HTML attributes. Hashing uses XXH3 through
Soenneker.Hashing.XxHash, producing a lowercase 64-bit hexadecimal hash for fast,
non-adversarial change detection.
Application-specific normalization
using System.Text.RegularExpressions;
using Soenneker.Html.Normalizer.Options;
var options = new HtmlNormalizationOptions();
options.RemoveSelectors.Add("[data-runtime-only]");
options.RemoveAttributes.Add("data-request-id");
options.Replacements.Add(new HtmlNormalizationReplacement(
"session-[a-f0-9]{32}",
"session-id",
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant));
string normalized = await normalizer.Normalize(renderedHtml, options);
Dependency injection
using Soenneker.Html.Normalizer.Registrars;
services.AddHtmlNormalizerAsSingleton();
// or services.AddHtmlNormalizerAsScoped();
Browser readiness is intentionally outside this package. Wait for hydration or another application-specific readiness signal before capturing and normalizing rendered HTML.
Normalized output is for comparison, not for rendering back to users: the default profile removes IDs and ID-reference attributes that can be functionally or accessibility significant. Disable the corresponding options when those values are part of the change you need to detect.
String-based replacements use a one-second regex match timeout. When supplying an existing Regex, construct it with an appropriate timeout yourself. XXH3 is a fast non-cryptographic hash; do not use it for signatures, password storage, or authenticity checks.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net10.0 is compatible. 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. |
-
net10.0
- Soenneker.AngleSharp.Parser (>= 4.0.59)
- Soenneker.Hashing.XxHash (>= 4.0.81)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 4.0.43 | 0 | 8/30/2026 |
| 4.0.42 | 0 | 8/30/2026 |
| 4.0.41 | 34 | 8/30/2026 |
| 4.0.40 | 37 | 8/30/2026 |
| 4.0.39 | 35 | 8/29/2026 |
| 4.0.38 | 88 | 8/26/2026 |
| 4.0.37 | 70 | 8/26/2026 |
| 4.0.36 | 78 | 8/24/2026 |
| 4.0.35 | 87 | 8/22/2026 |
| 4.0.34 | 89 | 8/21/2026 |
| 4.0.33 | 128 | 8/18/2026 |
| 4.0.32 | 93 | 8/18/2026 |
| 4.0.31 | 122 | 8/13/2026 |
| 4.0.30 | 91 | 8/12/2026 |
| 4.0.29 | 93 | 8/9/2026 |
| 4.0.28 | 88 | 8/8/2026 |
| 4.0.27 | 116 | 8/7/2026 |
| 4.0.26 | 91 | 8/7/2026 |
| 4.0.25 | 108 | 8/6/2026 |
| 4.0.24 | 119 | 8/2/2026 |