Package name: blanch (verified available on PyPI) Language: Python 3.10+ Replaces: mozilla/bleach (52.4M downloads/month, deprecated Jan 2023)
bleach is the de facto HTML sanitization library for Python with 52.4M monthly downloads, 2.8k stars, and 17k+ dependents. Mozilla deprecated it in January 2023 because it depends on html5lib, which is also unmaintained. The recommended alternative (nh3) has a fundamentally different API and lacks linkify support, requiring full rewrites to migrate. No maintained drop-in replacement exists.
blanch provides bleach's full API with modern internals:
- Same function signatures (
clean,linkify) - Same class APIs (
Cleaner,Linker,CSSSanitizer) - Same default constants (
ALLOWED_TAGS,ALLOWED_ATTRIBUTES,ALLOWED_PROTOCOLS) - Zero dependencies — uses
html.parserfrom stdlib instead of html5lib - Drop-in compatibility layer (
blanch.compat.bleach)
-
HTML Parser (
blanch/parser.py)- Built on
html.parser.HTMLParserfrom stdlib - Tokenizer that emits start/end/comment/data/entity events
- Handles malformed HTML gracefully (self-closing tags, missing end tags, attribute edge cases)
- Security-focused: normalizes entities, strips null bytes, handles nesting limits
- Built on
-
Sanitizer (
blanch/sanitizer.py)clean(text, tags, attributes, protocols, strip, strip_comments, css_sanitizer)— top-level functionCleanerclass — reusable sanitizer instance- Allowlist-based: only permitted tags/attributes/protocols pass through
- Disallowed tags are either escaped (
<script>) or stripped - Attribute values validated against protocol allowlist for URL attributes (href, src, etc.)
filtersparameter for post-processing pipeline
-
Linkifier (
blanch/linkifier.py)linkify(text, callbacks, skip_tags, parse_email)— top-level functionLinkerclass — reusable linkifier instance- URL detection via configurable regex
- Email detection with optional toggle
- Callback system for modifying generated
<a>tag attributes DEFAULT_CALLBACKSwithnofollowcallbackbuild_url_re(tlds, protocols)andbuild_email_re(tlds)helpers- HTML-aware: skips content inside specified tags (e.g.
<pre>,<code>)
-
CSS Sanitizer (
blanch/css_sanitizer.py)CSSSanitizer(allowed_css_properties, allowed_svg_properties)class- Strips disallowed CSS properties from
styleattributes - Validates CSS values (no url(), no expression(), no javascript:)
-
Constants (
blanch/constants.py)ALLOWED_TAGS— frozenset of safe HTML tags (a, abbr, acronym, b, blockquote, code, em, i, li, ol, strong, ul)ALLOWED_ATTRIBUTES— dict mapping tags to permitted attribute listsALLOWED_PROTOCOLS— frozenset({'http', 'https', 'mailto'})
-
Compatibility Layer (
blanch/compat/bleach.py)- Module that re-exports all public APIs matching
import bleachinterface bleach.clean,bleach.linkify,bleach.sanitizer.Cleaner, etc.- Users can alias:
import blanch.compat.bleach as bleach
- Module that re-exports all public APIs matching
blanch/
├── __init__.py # Public API: clean, linkify, Cleaner, Linker, constants
├── parser.py # HTML tokenizer/parser (stdlib html.parser based)
├── sanitizer.py # Cleaner class, clean() function, BleachSanitizerFilter compat
├── linkifier.py # Linker class, linkify() function, callbacks, regex builders
├── css_sanitizer.py # CSSSanitizer class
├── constants.py # ALLOWED_TAGS, ALLOWED_ATTRIBUTES, ALLOWED_PROTOCOLS
├── compat/
│ ├── __init__.py
│ └── bleach.py # Drop-in bleach module replacement
└── py.typed # PEP 561 marker
- Zero dependencies: stdlib
html.parserinstead of html5lib. Trades HTML5 spec conformance for independence and performance. bleach's security model is allowlist-based, so parser spec conformance matters less than in a full browser. - Type annotations: Full typing with
py.typedmarker for mypy/pyright. - Python 3.10+: Modern Python only. No Python 2 compat.
- ESM-style: Single
blanchpackage with submodules, not flat namespace.
- Core HTML parser with security hardening
- Sanitizer with full bleach.clean() API compatibility
- Linkifier with full bleach.linkify() API compatibility
- CSS sanitizer
- Drop-in bleach compatibility layer
- Comprehensive test suite (including bleach's own test cases)
- Published to PyPI as
blanch
- Port bleach's existing test suite (MIT-licensed) as baseline
- Add edge case tests for malformed HTML, XSS vectors, entity handling
- Test compatibility layer against bleach's public API contracts
- Fuzz testing with known XSS payloads (OWASP, XSS cheat sheets)