Skip to main content

htmlcompare

A Python library to check whether two HTML documents are "the same". It ignores differences which do not change what the document means, so a test does not fail just because a template engine emitted the attributes in a different order or wrote margin: 0px instead of margin: 0.

Usage

import htmlcompare

result = htmlcompare.compare_html(expected_html, actual_html)
if not result:
    print(result)

compare_html() returns a ComparisonResult which is true when both documents are the same. result.differences contains one Difference per mismatch, including the path to the node which caused it.

For tests the library provides two assertions:

from htmlcompare import assert_different_html, assert_same_html

assert_same_html('<div />', '<div></div>')
assert_different_html('<br>', '<p>')

Two files can also be compared on the command line:

htmlcompare expected.html actual.html

What is ignored

  • whitespace between tags, and <div /> written as <div></div>
  • the order of HTML attributes, and the order of the CSS classes inside a class attribute
  • an empty style or class attribute, which is treated like an absent one
  • HTML comments
  • the formatting of CSS. style attributes and <style> tags are parsed with a real CSS parser, so trailing semicolons, the order of declarations, the case of property, function and at-rule names, equivalent numeric spellings (.5px, 0.5px), the case of dimension units (1PX, 1px), the spelling of a URL (url(a.png), url("a.png")), a unit on a zero length and any whitespace CSS has no use for do not matter.

What is a difference

Something is only ignored when HTML and CSS guarantee that both spellings mean the same thing. Where the meaning can change, the documents differ:

  • whitespace which CSS gives a meaning to: .a .b is the descendant combinator and not .a.b, font-family: Arial Black is not font-family: ArialBlack
  • the order of declarations which can override each other, such as background and background-color
  • custom CSS syntax beginning with --, whose names are case-sensitive, and custom-property values, which var() substitutes literally: --x: 0px is not the same as --x: 0
  • conditional comments in both their forms, because dropping one changes which clients display the content

Malformed CSS never raises an exception. Whatever the CSS parser can not represent is compared as source text instead, which may report a difference which is not one but never hides one.

Options

compare_html() and both assertions take a CompareOptions instance:

option default effect
ignore_comments True ignore HTML comments
ignore_conditional_comments False ignore conditional comments as well
compare_document_prefix False compare text before the <!DOCTYPE> (e.g. {# … #} metadata emitted by a template engine). Such a prefix is always preserved, it is just not compared by default.

Limitations / Plans

No validation of conditional comments. Their condition is compared but not checked for validity. Not sure which library I can use here but at some point I'll likely need this as well.

JavaScript - for obvious reasons it will be impossible to implement perfect JS comparison but it might be possible to run some kind of "beautifier" to take care of insignificant stylistic changes. However I don't need this feature so this is unlikely to get implemented (unless contributed by someone else).

Custom hooks could help adapting the comparison to your specific needs. However I don't know which API would be best so this will wait until there are real-world use cases.

Better API: The current API is very minimal and implements just what I needed right now. I hope to improve the API once I use this project in more complex scenarios.

Other projects

xmldiff is a well established project to compare two XML documents. However it seems as if the code does not contain knowledge about specific HTML semantics (e.g. CSS, empty attributes, insignificant attribute order).

Misc

The code is licensed under the MIT license. It requires Python 3.9+.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

htmlcompare-0.5.0.tar.gz (60.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

htmlcompare-0.5.0-py3-none-any.whl (43.1 kB view details)

Uploaded Python 3

File details

Details for the file htmlcompare-0.5.0.tar.gz.

File metadata

  • Download URL: htmlcompare-0.5.0.tar.gz
  • Upload date:
  • Size: 60.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for htmlcompare-0.5.0.tar.gz
Algorithm Hash digest
SHA256 7b83a957f13c61661010bb23e981340b530597070a713bb38697e619852bef79
MD5 e4d50833b3a0293b4c479a45e8027011
BLAKE2b-256 448322a87a3495c2605394076282b668ea9c86c914fc94f7d1faeca9cfd3cb54

See more details on using hashes here.

Provenance

The following attestation bundles were made for htmlcompare-0.5.0.tar.gz:

Publisher: release.yml on FelixSchwarz/htmlcompare

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file htmlcompare-0.5.0-py3-none-any.whl.

File metadata

  • Download URL: htmlcompare-0.5.0-py3-none-any.whl
  • Upload date:
  • Size: 43.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for htmlcompare-0.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3403b27125b7da2bf4e04c37ffcfa3bc07791cf1b1eeddc5b9aebe6e64f7a7ec
MD5 65a236b02ca6755038f40b250188c327
BLAKE2b-256 e113e91df2087097ae7fcdad6b747ffce68c8c709ad60c2e16007691834f16e3

See more details on using hashes here.

Provenance

The following attestation bundles were made for htmlcompare-0.5.0-py3-none-any.whl:

Publisher: release.yml on FelixSchwarz/htmlcompare

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

0.5.0 This release

2 files

0.4.1

2 files

0.4.0

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.1

2 files

0.2

2 files

0.1

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page