The hardware and bandwidth for this mirror is donated by METANET, the Webhosting and Full Service-Cloud Provider.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]metanet.ch.
The Public Suffix List
website catalogs implementations in C, C#, C++, Go, Haskell, Java,
JavaScript, Perl, PHP, Python, Ruby, Rust, Swift, and more — but no R.
pslr fills that gap, and it is built to be a
reproducibility- and correctness-first engine rather than a
quick suffix splitter.
The table compares pslr with a representative set of the
most established libraries from that catalog, across the dimensions that
matter for correct, auditable suffix handling. ✅ first-class · ◐
partial/limited · ⚠ with a caveat · ❌ absent.
| Library (language) | Full algorithm (*/!) |
ICANN / PRIVATE / both | IDN + Punycode | Offline default + explicit refresh | Queryable provenance | Compiled core | Strict input validation | Unlisted-TLD policy configurable |
|---|---|---|---|---|---|---|---|---|
| pslr (R) | ✅ | ✅ 3-way | ✅ in & out | ✅ bundled; validated HTTPS-only
psl_refresh() |
✅ list and normalization identity | ✅ cpp11 |
✅ rejects URLs, IPv4, IPv6 | ✅ unknown= |
| libpsl (C) | ✅ | ✅ 3-way | ✅ | ✅ bundled; OS-package update | ◐ sha1 + mtime | ✅ | ◐ | ✅ |
| x/net/publicsuffix (Go) | ✅ | ◐ icann flag |
❌ ASCII only | ✅ embedded; bump module | ◐ date constant | ✅ | ◐ | ❌ |
| publicsuffix-go (Go) | ✅ | ◐ toggle private | ✅ | ✅ embedded | ❌ | ❌ | ◐ | ✅ |
| psl crate (Rust) | ✅ | ◐ per-suffix type | ✅ | ✅ compiled-in | ◐ dated releases | ✅ | ❌ | ◐ |
| tldextract (Python) | ✅ | ◐ private on/off | ✅ | ⚠ network-first; offline opt-in | ❌ | ❌ | ◐ | ❌ |
| publicsuffixlist (Python) | ✅ | ◐ exclude private | ✅ | ✅ bundled + updater | ◐ date in version | ❌ | ❌ | ❌ |
| public_suffix (Ruby) | ✅ | ◐ ignore_private |
❌ caller pre-encodes | ✅ bundled | ❌ | ❌ | ◐ | ✅ |
| php-domain-parser (PHP) | ✅ | ✅ 3-way | ✅ | ⚠ not bundled; PSR-16 cache | ◐ isKnown flags |
❌ | ◐ | ◐ |
| tldts (JS/TS) | ✅ | ◐ allowPrivateDomains |
✅ | ✅ embedded; npm bump | ◐ submodule pin | ◐ optional WASM | ✅ | ◐ |
Guava InternetDomainName (Java) |
◐ | ✅ registry vs public | ✅ | ◐ in-jar; bump Guava | ❌ | ❌ | ◐ | ❌ |
pslr does differentlypsl_version() records the list identity (source, commit,
date, SHA-256) and the normalization identity (normalizer
package + version, profile, Unicode version). A PSL answer depends on
both which list answered and how the host was
normalized — pslr is the only surveyed library that
surfaces both, so a result is genuinely reproducible.tests.txt vectors, pinned in lockstep
with the bundled snapshot and run on every check.psl_refresh()
is the only code that touches the network — HTTPS-only,
credential- and downgrade-rejecting, size-capped, conditional when it
can be, published append-only. This is stricter than network-first
designs and pairs with the reproducibility story rather than fighting
it.psl_status() separates “a check is due” from “a newer list
was actually observed”, and never infers the second from snapshot age.
Surveyed libraries report a date or nothing at all.psl_diff()
reports what actually changed between two snapshots — canonically,
offline, keyed on each rule’s logical identity so a wildcard/exception
change or an ICANN/PRIVATE move reads as one change rather than an
unrelated removal and addition. No surveyed library offers this.invalid = "na" / "error" lets you choose
silent NA or a hard stop. Many libraries are deliberately
lenient.NA-safe, name-preserving.
Every function operates on a whole character vector — the idiomatic
shape for data work in R.psl_use() /
psl_refresh()) unless a call passes engine =,
a psl_engine() built for one specific snapshot.rurl.These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.