pygarble: a first line of defence for text¶
Local secrets, PII and profanity screening, plus independent gibberish detection. No LLM calls or inference-model downloads.
pygarble screens text with fixed rules, checksums, a word list, character statistics and encoding checks. The base install has no runtime dependencies; optional local backends extend coverage when explicitly selected. Every finding has a kind, span, confidence and reason, without the matched text. This documentation describes 0.11.0; see Installation for installing it and Upgrading when upgrading from 0.8.0.
from pygarble.screening import Scanner
scanner = Scanner(max_input_length=100_000)
report = scanner.scan("mail jane@example.com, key AKIAIOSFODNN7EXAMPLE")
assert report.kinds() == ("aws_access_key_id", "email")
assert scanner.redact("mail jane@example.com").text == "mail [EMAIL]"
Use Standalone screening and optional backends for the three rule categories, optional
backends and document CLI. Use pygarble.gibberish for gibberish detection.
The original from pygarble import Scanner still runs all four categories;
its guide is Combined screening and redaction. See Module layout and compatibility for module ownership
and old import pointers.
The gibberish category is English-specific. Meaningful Hindi and other non-English text may be flagged; this is expected for English-specific scoring. It is not a language identifier or a semantic nonsense detector. Scores are heuristics, not calibrated probabilities.
See Installation to install the package.
Research and measured results¶
A preprint measures the gibberish detector on two public English datasets,
Survey Junk and Tweets vs. Random Strings, against two CPU baselines at
default settings. The english_fusion profile captures 89.5% of the survey
junk and recalls 99.1% of the random strings at a precision of 0.906, from a
1.05 MB install. A Markov-chain baseline flags fewer tweets, a language
identifier captures more survey junk, and the default english profile
flags 33.2% of tweets. Read Benchmark and preprint for every result, the
limitations and the reproduction commands.
Citing pygarble¶
Cite the preprint for the benchmark results and the software entry for the library. The preprint is archived on Zenodo under DOI 10.5281/zenodo.23312785, which always resolves to the latest version.
@misc{rao2026pygarble,
author = {Rao, Ujjwal Singh and Singh, Ricky},
title = {How Much Junk Do Rules Catch? Evaluating and Tuning pygarble, a Dependency-Free Gibberish Screener, on Survey Responses and Social-Media Text},
year = {2026},
howpublished = {Preprint, Zenodo},
doi = {10.5281/zenodo.23312785},
url = {https://doi.org/10.5281/zenodo.23312785}
}
@misc{pygarble,
author = {Rao, Ujjwal Singh and Singh, Ricky},
title = {pygarble: local screening of text for secrets, {PII}, profanity and gibberish},
year = {2026},
howpublished = {\url{https://github.com/brightertiger/pygarble}},
note = {Version 0.11.0, https://github.com/brightertiger/pygarble/releases/tag/v0.11.0}
}
Screening
Gibberish
- Choosing strategies
- What the preprint tells us about strategy choice
- Lexical and statistical strategies
- English-reference window strategies
- Fisher voting and the english_fusion profile
- Control characters: new in 0.11.0
- Localized anomalies: new in 0.11.0
- Keyboard paths and repetition
- LLM output: new in 0.11.0
- Tune on your own data
- Detection Strategies
- Calibrating the threshold
Maintainers
Gibberish quick start¶
from pygarble.gibberish import EnsembleDetector
detector = EnsembleDetector()
detector.predict("Hello world") # False
detector.predict("asdfghjkl") # True
detector.predict("नमस्ते दुनिया") # True: English-specific checks
detector.predict("hello\x00world") # True: control artifact
Use profile="corruption" to check encoding/control artifacts independently
of English plausibility, or profile="english_extended" for more aggressive
localized and repetition detection. See API Reference for explanations, batching,
per-strategy configuration, and abstention behavior.
Evaluation¶
The Benchmark and preprint guide reports the preprint benchmark and explains its
limitations. It uses two public English datasets: Survey Junk (Kaggle, 3,513
junk-only rows, measuring the capture rate of junk) and Tweets vs. Random
Strings (Hugging Face, 9,971 rows, measuring precision, recall and
false-positive rate). The baselines, gibberish-detector 0.1.1 and lingua
2.2.0, were run as installed with default settings, so the comparison measures
out-of-the-box behaviour. Fast engineering regression checks remain separate
from research results. Run make benchmark-verify to recompute the preprint
metrics from the committed predictions (see paper/scripts/benchmark/README.md
to re-score from raw data); the full write-up is at
doi:10.5281/zenodo.23312785.