mrkeyoor.com_
Tue 22 Sept 01:44 UTC
PyPIUtilsupdated 21 Sept 2026

tldextract review

tldextract 5.3.2 separates a hostname into subdomain, registrable domain, and public suffix by consulting the Public Suffix List used for browser cookie boundaries. A dot split gets forums.bbc.co.uk wrong because co.uk is one suffix; tldextract returns forums, bbc, and co.uk. ExtractResult also exposes fqdn, top_domain_under_public_suffix, reverse_domain_name, IP helpers, and an is_private flag. Version 5.3.2 fixes stray dots in reverse_domain_name when the suffix or domain is empty, corrects extract_urllib documentation, and documents IDNA representation and the library's handling of unlisted suffixes. Its default first lookup may fetch and cache the current PSL, which is the main production surprise.

Verdict

tldextract 5.3.2 installed 8 packages in 0.3 seconds and used 4 MB in our sandbox, with a 0.45-second import and 0 audit findings. It is the right tool for PSL-aware site boundaries once you disable or control the first-run fetch, normalize hostnames, and choose how private suffixes should behave.

We installed it

Lab card: what happened when we installed tldextractScreenshot of tldextract documentation
Install✓ · 0.3s8 packages on disk · 4 MB
Importimport tldextract in 0.45s · pure Python · py.typed · requires Python >=3.10
Known vulns0(pip-audit)

Answers from our run

Does tldextract install cleanly?

Yes. In a fresh container with an empty cache, pip install tldextract finished in 0.3s, leaving 8 packages and 4 MB on disk. pip-audit reported no known vulnerabilities.

What does tldextract need to run?

Python >=3.10, and nothing compiled: it is pure Python. In our run import tldextract succeeded in 0.45s, and the package ships py.typed for type checkers.

tldextract or publicsuffix2: which should you use?

publicsuffix2: Choose it for an older PSL interface that works from a packaged list and follows the publicsuffix API. tldextract 5.3.2 installed 8 packages in 0.3 seconds and used 4 MB in our sandbox, with a 0.45-second import and 0 audit findings.

When should you not use tldextract?

A cold process cannot perform network I/O. The default extractor may download the PSL on its first call, and its fetch timeout is unset unless TLDEXTRACT_CACHE_TIMEOUT is configured.

API stability4/5The callable extractor and ExtractResult fields subdomain, domain, suffix, and is_private have remained familiar through the 5.x line. Version 5.3.2 changes a reverse_domain_name edge case and documentation without altering normal extraction. One migration is already announced: registered_domain is deprecated for top_domain_under_public_suffix and targeted for removal in 6.0.0. Callers that use derived properties should finish that rename before the next major release.
Docs4/5The README now gives direct recipes for offline use, custom cache paths, explicit updates, private suffixes, local and remote lists, extra internal suffixes, validation with urlsplit, and CLI operation. Version 5.3.2 also corrects extract_urllib placement and documents IDNA representation plus unknown-suffix behavior. The default network timeout and fallback consequences are less prominent than their production impact, so deployment still needs a separate cache policy.
Maintenance5/5PyPI released 5.3.2 on August 8, 2026 and GitHub records a push minutes later. The patch fixes reverse_domain_name output, repairs API documentation, adds doctest coverage, and explains hostname representation limits. The repository is not archived, has 2,014 stars, and GitHub lists 19 open issues and pull requests. Current packaging and documentation work shows an actively maintained utility with a contained backlog.
Ecosystem4/5The supplied weekly record is 9,390,843 downloads, and the project has 2,014 GitHub stars. tldextract uses the browser-oriented Public Suffix List, includes a command-line updater, accepts local mirrors and extra suffixes, supports public and private sections, and ships typing markers. It remains a focused boundary lookup tool: URI validation, IDNA canonicalization, DNS resolution, and policy decisions must come from other packages or application code.

Use it if

  • Analytics, rate limiting, or deduplication must group forums.bbc.co.uk with bbc.co.uk while keeping unrelated co.uk registrations separate.
  • Security rules need site boundaries based on the same Public Suffix List concept used by browsers for cookie scope.
  • Tenant isolation needs private suffixes such as blogspot.com or github.io to count as boundaries through include_psl_private_domains.
  • The service can manage a cached PSL snapshot or an intentionally scheduled update from the public list or an internal mirror.
Skip it if

Setup reality

We installed tldextract 5.3.2 in 0.3 seconds in a clean Python 3.12 Bookworm sandbox. The environment contained 8 packages using 4 MB afterward. tldextract declares 4 direct dependencies, is pure Python, requires Python 3.10 or newer, and ships py.typed. import tldextract completed in 0.45 seconds. pip-audit reported 0 known vulnerabilities. The distribution metadata did not provide a license value in our measurement.

The module-level extractor can fetch publicsuffix.org on its first cold lookup, try a GitHub mirror, and cache the parsed list below the user's cache directory. TLDEXTRACT_CACHE or cache_dir changes that location. TLDEXTRACT_CACHE_TIMEOUT bounds network waiting. A read-only filesystem, missing home directory, or blocked egress can therefore turn an ordinary hostname split into a startup problem. suffix_list_urls=() disables HTTP and uses the bundled snapshot.

Build one TLDExtract instance and reuse it. Each instance prepares its own suffix matcher on first use, so constructing one inside a request handler repeats work. The cache does not expire by age. Run tldextract --update deliberately, vendor a list through a file URL, or pin the bundled snapshot if identical answers across replicas matter. fallback_to_snapshot=True can hide a download failure by returning results from the package's older copy.

tldextract finds suffix boundaries and does not certify input. Free text can be returned as a domain, unknown final labels yield an empty suffix, and case plus Unicode or ACE spelling are preserved. Validate the hostname with a URL or IDNA layer before using it in an allowlist. Decide whether the PSL PRIVATE section counts for your tenancy model. Migrate registered_domain calls to top_domain_under_public_suffix before version 6.

Patterns

Split a hostname at its public suffix extract-basic

import tldextract

print(tldextract.extract('http://forums.news.cnn.com/'))
# ExtractResult(subdomain='forums.news', domain='cnn', suffix='com', is_private=False)

print(tldextract.extract('http://forums.bbc.co.uk/'))
# ExtractResult(subdomain='forums', domain='bbc', suffix='co.uk', is_private=False)

The shared module extractor accepts hostnames and full URLs. Scheme, port, path, and query do not become domain labels.

Return the registrable site name registrable-domain

ext = tldextract.extract('http://forums.bbc.co.uk/path')

print(ext.top_domain_under_public_suffix)  # 'bbc.co.uk'
print(ext.fqdn)                            # 'forums.bbc.co.uk'

top_domain_under_public_suffix is the 5.x replacement for deprecated registered_domain. It is empty for an address with no recognized suffix.

Use only the packaged suffix snapshot disable-network-fetch

import tldextract

extract = tldextract.TLDExtract(suffix_list_urls=())
result = extract('http://www.google.com')

An empty URL tuple prevents the first call from downloading the PSL. Results then stay tied to the installed package snapshot.

Share one configured extractor reuse-one-extractor

EXTRACT = tldextract.TLDExtract(suffix_list_urls=())

def site_of(url: str) -> str:
    return EXTRACT(url).top_domain_under_public_suffix

Create the instance at module scope so request handlers reuse the prepared suffix matcher and the same cache policy.

Choose a writable cache and timeout custom-cache-location

import tldextract

extract = tldextract.TLDExtract(cache_dir='/var/cache/tldextract')

# Environment equivalents:
# TLDEXTRACT_CACHE=/var/cache/tldextract
# TLDEXTRACT_CACHE_TIMEOUT=2.0

The default user cache may fail in a read-only container. TLDEXTRACT_CACHE_TIMEOUT limits the initial remote-list request.

Treat hosted tenants as separate sites private-domains

import tldextract

extract = tldextract.TLDExtract(include_psl_private_domains=True)
print(extract('waiterrant.blogspot.com'))
# ExtractResult(subdomain='', domain='waiterrant', suffix='blogspot.com', is_private=True)

Private suffix handling is off by default. Enable it when each blogspot.com or github.io tenant must have its own boundary.

Refresh suffix data on a schedule update-suffix-list

# shell
tldextract --update

# Python
extract = tldextract.TLDExtract()
extract.update(fetch_now=True)

The cache has no automatic age expiry. Schedule updates or replace the cached file if current PSL rules matter to the service.

Extract from an existing SplitResult extract-from-parsed-url

from urllib.parse import urlsplit
import tldextract

extract = tldextract.TLDExtract(suffix_list_urls=())
parts = urlsplit('https://a.b.example.com/path?q=1')
print(extract.extract_urllib(parts))

extract_urllib is an instance method in 5.3.2. urlsplit handles URL structure first; tldextract then finds the suffix boundary.

Separate IP and local-host results handle-non-domains

print(tldextract.extract('http://127.0.0.1/x').ipv4)
print(tldextract.extract('https://[2001:db8::1]/').ipv6)

local = tldextract.extract('http://localhost:8080')
if not local.suffix:
    print('No recognized public suffix')

An empty suffix covers localhost, unknown endings, and invalid text. Check IP helpers and validate input rather than trusting domain alone.

Canonicalize before comparing sites normalize-case

res = tldextract.extract('HTTP://WWW.EXAMPLE.COM')
site = res.top_domain_under_public_suffix.lower()
print(site)  # 'example.com'

Suffix matching ignores case, but returned strings preserve it. IDNA inputs also need one validated A-label representation for security comparisons.

Load internal and vendored suffix rules custom-suffix-list

import tldextract

corp = tldextract.TLDExtract(extra_suffixes=['internal', 'corp.example'])

vendored = tldextract.TLDExtract(
    suffix_list_urls=['file:///opt/psl/public_suffix_list.dat'],
    cache_dir='/var/cache/tldextract',
    fallback_to_snapshot=False,
)

extra_suffixes covers names that will never enter the public list. Disabling fallback makes an unreadable vendored file fail instead of using the packaged snapshot.

Create a reverse-domain identifier reverse-domain-name

result = tldextract.extract('api.eu.example.co.uk')
print(result.reverse_domain_name)
# uk.co.example.eu.api

Version 5.3.2 fixes extra dots in reverse_domain_name when either domain or suffix is empty. It does not normalize case or IDNA form.

Alternatives

PackageRegistryPick it when
publicsuffix2PyPIChoose it for an older PSL interface that works from a packaged list and follows the publicsuffix API.
publicsuffixlistPyPIChoose it when you want a compact PSL lookup package whose suffix data updates through package releases.
uritoolsPyPIChoose it when the real job is parsing, classifying, resolving, or composing URI components rather than finding registration boundaries.

More utils guides

lru-cache · ajv · type-fest · p-limit · find-up · js-yaml · the whole shelf →

How this guide is made: grounded in the library's documentation, release notes, changelog, and issue history, on a fixed rubric — not a hands-on install of every release. The 50 most-downloaded entries are additionally install-verified in clean containers. Corrections: contact the desk.