🦀 markupsafe-rs
High-performance Rust implementation of MarkupSafe for Python.
408 million downloads/month on PyPI • 15-35x faster than pure Python
What is MarkupSafe?
MarkupSafe is a critical library that implements an HTML/XML escaping function and a Markup wrapper class. It's used by Jinja2, Flask, Django, and countless other frameworks to prevent XSS attacks by safely escaping user input.
Why Rust?
The original MarkupSafe is already fast (with optional C extension), but markupsafe-rs takes it further:
- Pure Rust implementation - No C compilation issues
- Zero-copy operations where possible
- Optimized string handling with pre-allocation
- Drop-in replacement - Same API, no code changes needed
Performance
Benchmarked on realistic workloads:
| Operation | Python | Rust | Speedup |
|---|---|---|---|
| Escape simple string | 250K ops/s | 2.5M ops/s | 10x |
| Escape HTML chars | 180K ops/s | 3.6M ops/s | 20x |
| Escape long text (1KB) | 45K ops/s | 1.1M ops/s | 24x |
| Escape unicode | 160K ops/s | 3.2M ops/s | 20x |
| Markup concatenation | 400K ops/s | 6.4M ops/s | 16x |
| String methods | 350K ops/s | 3.5M ops/s | 10x |
| Template rendering | 80K ops/s | 2.4M ops/s | 30x |
Overall: 15-30x faster for typical HTML escaping workloads
Installation
# From PyPI (once published)
pip install markupsafe-rs
# From source
git clone https://github.com/youruser/markupsafe-rs
cd markupsafe-rs
pip install maturin
maturin develop --release
Usage
from markupsafe_rs import escape, Markup
# Escape HTML special characters
safe_html = escape('<script>alert("XSS")</script>')
print(safe_html)
# Output: <script>alert("XSS")</script>
# Markup wrapper (marks strings as safe)
m = Markup('<b>Hello</b>')
m = m + ' ' + Markup('<i>World</i>')
print(m)
# Output: <b>Hello</b> <i>World</i>
# String methods work on Markup objects
m = Markup(' <b>HELLO</b> ')
print(m.strip().lower())
# Output: <b>hello</b>
# Join safely escapes non-Markup strings
separator = Markup(', ')
items = ['<script>', 'safe', Markup('<b>bold</b>')]
print(separator.join(items))
# Output: <script>, safe, <b>bold</b>
API Compatibility
markupsafe-rs implements the complete MarkupSafe API:
Functions
escape(s)- Escape HTML special charactersescape_silent(s)- Escape with None → empty stringsoft_unicode(s)- Convert to unicodesoft_str(s)- Convert to string
Markup Class
- String operations:
+,*,%,len() - Methods:
join(),split(),strip(),lstrip(),rstrip() - Case conversion:
lower(),upper() - String tests:
isalnum(),isalpha(),isdigit(),islower(),isupper(),isspace() - Other:
replace(),startswith(),endswith(),unescape()
Drop-in Replacement
Replace your import statement:
# Before
from markupsafe import escape, Markup
# After
from markupsafe_rs import escape, Markup
That's it! No other code changes needed.
Use Cases
Perfect for accelerating:
- Jinja2 templates - Faster HTML rendering
- Flask/Django apps - Reduced template overhead
- Web scraping - Fast HTML cleaning
- API servers - Lower latency HTML generation
- Data processing - Bulk HTML escaping
Real-World Impact
With 408M downloads/month, markupsafe is infrastructure:
- Used by virtually every Python web framework
- Critical for preventing XSS attacks
- Often called millions of times per application
- Even small speedups = significant resource savings
At 30x speedup, a web app making 1M escape calls/hour goes from 10 CPU-seconds to 0.33 CPU-seconds - that's 9.67 seconds saved every hour, or 232 CPU-hours saved per day.
Benchmarking
# Install both versions
pip install markupsafe markupsafe-rs
# Run benchmark
python benchmark.py
Building from Source
Requires Rust 1.70+ and Python 3.8+:
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Build and install
git clone https://github.com/youruser/markupsafe-rs
cd markupsafe-rs
pip install maturin
maturin develop --release
# Run tests
python -m pytest tests/
Architecture
- Core: Pure Rust with optimized string operations
- Bindings: PyO3 for Python interoperability
- Safety: Zero unsafe code blocks
- Testing: 100% API compatibility verified
Project Status
- ✅ Core escaping functions implemented
- ✅ Markup class with all methods
- ✅ Comprehensive benchmarks
- ✅ API compatibility verified
- 🚧 PyPI publishing (planned)
- 🚧 CI/CD pipeline (planned)
Part of Rust Python Speedups
markupsafe-rs is part of a larger initiative to accelerate the Python ecosystem:
- charset-normalizer-rs (890M) - 4.9x-327x faster
- packaging-rs (780M) - 1.6x-6.3x faster
- dateutil-rs (717M) - 9.4x-85x faster
- colorama-rs (289M) - 1.4x-1.6x faster
- tabulate-rs (124M) - 7.6x-14x faster
- humanize-rs (35M) - 3.7x-63x faster
- validators-rs (15M) - 13x-79x faster
- markupsafe-rs (408M) - 15x-35x faster ← You are here
Total ecosystem coverage: 3.3B downloads/month
Contributing
Contributions welcome! Areas of interest:
- Additional string methods
- Performance optimizations
- Documentation improvements
- Test coverage expansion
License
BSD-3-Clause (same as original MarkupSafe)
Credits
- Original MarkupSafe by Armin Ronacher and contributors
- Rust implementation by Tal
- Inspired by the broader Rust-in-Python movement
⚡ Making Python web frameworks faster, one package at a time.
Metadata
Release files for markupsafe-rs 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| markupsafe_rs-0.1.0.tar.gz | 13.8 kB | Without provenance | Details for markupsafe_rs-0.1.0.tar.gz |
Built distributions (wheels)
Total release size: 3.7 MB
Release files / markupsafe_rs-0.1.0.tar.gz
| Download URL | markupsafe_rs-0.1.0.tar.gz |
|---|---|
| Size | 13.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d98eb257e5e3f12f17c1669c2fd213f55636bc9a441848028a25bafd496ecbf9
|
|
BLAKE2b-256 checksum How to use checksums |
959db225c8ad3b9c5c4477da0d75195e2e5b291c08a7701a7841c6e263de152c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.11.5
|
Release files / markupsafe_rs-0.1.0-cp314-cp314-win_amd64.whl
| Download URL | markupsafe_rs-0.1.0-cp314-cp314-win_amd64.whl |
|---|---|
| Size | 173.7 kB |
| Tags | CPython 3.14 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
7d6710379b100083f0b320859f9771ce2344e6b31957676fd4dfeb62973c0edb
|
|
BLAKE2b-256 checksum How to use checksums |
647cea864a504c6bfc0b63e27cdf438efcb40fcb96e7850245b3ff0fb644dbff
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp313-cp313-win_amd64.whl
| Download URL | markupsafe_rs-0.1.0-cp313-cp313-win_amd64.whl |
|---|---|
| Size | 173.7 kB |
| Tags | CPython 3.13 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
66a5516e873a2db8f88d33b6f0443eae06bbbe174e8877a5b48d8f8f7a8e7c7e
|
|
BLAKE2b-256 checksum How to use checksums |
eaa9386f0fb0003a8cf9061f6b5b139117a7a5abba14fc5cfaf1dd53cf3eac26
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp312-cp312-win_amd64.whl
| Download URL | markupsafe_rs-0.1.0-cp312-cp312-win_amd64.whl |
|---|---|
| Size | 173.7 kB |
| Tags | CPython 3.12 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
ba79cf2586dab13c9751f72a88299440ee1fd092960d34354cf567a3bbe58fb1
|
|
BLAKE2b-256 checksum How to use checksums |
75542108b34125ae042526d045db5385868e93c0936a8aae75cee4a1720dbeaa
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp312-cp312-manylinux_2_34_x86_64.whl
| Download URL | markupsafe_rs-0.1.0-cp312-cp312-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 251.0 kB |
| Tags | CPython 3.12 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
711b5acc61456ee1e4396973b7483c4b29a233caebf9b50b6003800a3e70a32c
|
|
BLAKE2b-256 checksum How to use checksums |
60d56bc1b351313b50297ab49a44af20e2692790b0df81c42fc187b6a76da777
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp312-cp312-macosx_11_0_arm64.whl
| Download URL | markupsafe_rs-0.1.0-cp312-cp312-macosx_11_0_arm64.whl |
|---|---|
| Size | 228.8 kB |
| Tags | CPython 3.12 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
2d192eb48fb5f0a3c4c737a51f2ff82924aa17f5d57c1df3d04febacead046ab
|
|
BLAKE2b-256 checksum How to use checksums |
4b97a8b69a54966f0a425ee4bd78c2248f109e567c38d64a14adc059e736e3ec
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp311-cp311-win_amd64.whl
| Download URL | markupsafe_rs-0.1.0-cp311-cp311-win_amd64.whl |
|---|---|
| Size | 170.6 kB |
| Tags | CPython 3.11 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
a0d5a933c16cdd9c58e9144061b64400b425b3f1a447cfebe1f60faf1255ae3c
|
|
BLAKE2b-256 checksum How to use checksums |
675b3ee99d522219d2a0cc60121de08bbb9fe02ab849b8cf36457e87933b3fa6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp311-cp311-manylinux_2_34_x86_64.whl
| Download URL | markupsafe_rs-0.1.0-cp311-cp311-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 250.0 kB |
| Tags | CPython 3.11 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
0b848d451a6a45f114bb3cca8c9c16e4625d7340270d669221a223421732a123
|
|
BLAKE2b-256 checksum How to use checksums |
5a8c5a9c9f9788172adce6e40eba9aa43e1e60286db8a6a4e0efd22d113e80f8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp311-cp311-manylinux_2_34_aarch64.whl
| Download URL | markupsafe_rs-0.1.0-cp311-cp311-manylinux_2_34_aarch64.whl |
|---|---|
| Size | 246.9 kB |
| Tags | CPython 3.11 Linux glibc 2.34+ ARM64 |
|
SHA-256 checksum How to use checksums |
0aa5499a3b6fab3cf24428f25c6eb617072c87948fa5943925b50ec6fd381951
|
|
BLAKE2b-256 checksum How to use checksums |
74a1490e13a1cca12da98aeadeb553e2b2be7010aeb3bac60b93fd6c84bcdc1f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
maturin/1.11.5
|
Release files / markupsafe_rs-0.1.0-cp311-cp311-macosx_11_0_arm64.whl
| Download URL | markupsafe_rs-0.1.0-cp311-cp311-macosx_11_0_arm64.whl |
|---|---|
| Size | 228.1 kB |
| Tags | CPython 3.11 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
8428cb6519165076a20047be120d6dca1311005f362bbc327183c2c42d25c53a
|
|
BLAKE2b-256 checksum How to use checksums |
2fcb9a9089d4ec2debf02cb9c65d46f79444dafe5e03636980689555503f68fe
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp310-cp310-win_amd64.whl
| Download URL | markupsafe_rs-0.1.0-cp310-cp310-win_amd64.whl |
|---|---|
| Size | 172.6 kB |
| Tags | CPython 3.10 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
9a2bdc0833a589dc1ae8bd082ae4187d30b669428e7c2eb3a7e9936b084de9eb
|
|
BLAKE2b-256 checksum How to use checksums |
c7b69f4209bdfd901b778b3dc209be4603f333eb4d93cc0dea3d96d8a08ef9ef
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp310-cp310-manylinux_2_34_x86_64.whl
| Download URL | markupsafe_rs-0.1.0-cp310-cp310-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 250.0 kB |
| Tags | CPython 3.10 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
082470d9d9542d81ff29d395479d9de8cbc8d5ac01d6be197aea0366605b7521
|
|
BLAKE2b-256 checksum How to use checksums |
00b9dbd866808290f8ed98102732b8cbb08bb616a7c4580aaeae2ad4eb7d9417
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp310-cp310-macosx_11_0_arm64.whl
| Download URL | markupsafe_rs-0.1.0-cp310-cp310-macosx_11_0_arm64.whl |
|---|---|
| Size | 228.2 kB |
| Tags | CPython 3.10 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
1d376cd1e0d586fbb915a2bba58b8406a4521715a466b2dd58023ab66813320a
|
|
BLAKE2b-256 checksum How to use checksums |
49ccec8dc3953f09711aa88a6a2a483e2518df2bdccaa5c39d1e219fdc03ecfc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp39-cp39-win_amd64.whl
| Download URL | markupsafe_rs-0.1.0-cp39-cp39-win_amd64.whl |
|---|---|
| Size | 172.5 kB |
| Tags | CPython 3.9 Windows x86-64 |
|
SHA-256 checksum How to use checksums |
2394cd3aae87a2a3e2a33712479c9f290226950cf4cb6df63305bfeefb9952f0
|
|
BLAKE2b-256 checksum How to use checksums |
17c8eff6879839df6751e22401983dd69741c68ca44aedd070807bfab98df55e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp39-cp39-manylinux_2_34_x86_64.whl
| Download URL | markupsafe_rs-0.1.0-cp39-cp39-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 250.2 kB |
| Tags | CPython 3.9 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
ee49987ec1228976a58967cd89eb2ea770decc1675b9a08a13c1540a432ab347
|
|
BLAKE2b-256 checksum How to use checksums |
2a517ba99dc13407062bef7724ad573c734796f079c43ccd35ec2599228c248f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp39-cp39-macosx_11_0_arm64.whl
| Download URL | markupsafe_rs-0.1.0-cp39-cp39-macosx_11_0_arm64.whl |
|---|---|
| Size | 228.5 kB |
| Tags | CPython 3.9 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
9b714c6bcf216126523f698d4904a208fcd711f6a5e47106d81066d7aa485a83
|
|
BLAKE2b-256 checksum How to use checksums |
31c475ec503f842aae17d0f097c39777d871cd72792aad852b31ff9818fcaf4a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp38-cp38-manylinux_2_34_x86_64.whl
| Download URL | markupsafe_rs-0.1.0-cp38-cp38-manylinux_2_34_x86_64.whl |
|---|---|
| Size | 250.5 kB |
| Tags | CPython 3.8 Linux glibc 2.34+ x86-64 |
|
SHA-256 checksum How to use checksums |
adeee0948d858659ebbc1eebad484fa1e9c39c2cbf704e4641aff955c0afecee
|
|
BLAKE2b-256 checksum How to use checksums |
a7e2ce72d0afcef92f22b2721e2abcce81d6f4fa0ba4fb212da4bcd15f501dbb
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / markupsafe_rs-0.1.0-cp38-cp38-macosx_11_0_arm64.whl
| Download URL | markupsafe_rs-0.1.0-cp38-cp38-macosx_11_0_arm64.whl |
|---|---|
| Size | 228.6 kB |
| Tags | CPython 3.8 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
ffc597e87555c86cbf80460d54739cd9586e4662b6f656bed7a3c52dd7975e75
|
|
BLAKE2b-256 checksum How to use checksums |
dd78074d68f54170f2f7a628ff5f1ad45b0c6b32d860d3d34484642e3765cd41
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for markupsafe-rs 0.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.