Domain Extractor
Paste a mail thread, a log, a scraped page or a column of URLs, and every domain in it is listed on the right as you type. The one decision that makes this job hard is where a domain ends, and it is the decision most extractors get wrong: cutting at the last two labels turns a.b.co.uk into co.uk, which is a registry rather than a domain, and turns tenant.github.io into github.io, which belongs to somebody else. This page ships 907 Public Suffix List rules transcribed on 2026-09-21, the private section included, and applies them in your browser with no lookup of any kind, so a.b.co.uk gives b.co.uk and tenant.github.io is kept whole. The first ten runs are worked out under the stage, each showing the suffix that made the cut, so a surprising answer can be checked instead of trusted, and the CSV carries that rule for every row. What was passed over is on screen too: an IP address is named as an IP address, a host with nothing registrable above its suffix is named as that, and a file name such as notes.txt is named as an unknown top-level domain, instead of arriving quietly in the list as a domain. Repeats fold into one row with a count, subdomains can be kept instead of cut, and the whole list copies one per line or downloads as a CSV that carries the rejected rows as well.
Paste text on the left, or .
Nothing to read yet. Paste text on the left and every domain in it is listed on the right. Cut by 907 Public Suffix List rules dated 2026-09-21, private section included, with no lookup of any kind.
The first 10 runs are worked out under the stage, each with the suffix that made the cut, so a surprising answer can be checked instead of trusted: a.b.co.uk is cut to b.co.uk by the rule co.uk, while tenant.github.io is kept whole by the private rule github.io. The CSV carries that rule for every row. 907 rules and 663 top-level domains are shipped with the page, transcribed on 2026-09-21, and nothing you paste leaves this browser.
Common questions
- How does it decide where a domain ends?
- It runs the Public Suffix List algorithm over the rules it ships. Starting from the whole host, each suffix is looked up in the table: an exception rule beginning with an exclamation mark wins outright, otherwise the longest matching rule wins, and a rule beginning with a star matches exactly one label. The registrable domain is that public suffix plus the one label in front of it. Where the table says nothing, the default rule applies and the name is cut at its last label, which is the right answer for com, net, dev and every other registry that sells names directly. That is why a.b.c.co.uk gives c.co.uk, foo.bar.ck gives foo.bar.ck under the star rule for ck, and shop.www.ck gives www.ck through the exception rule the list carries for it.
- Why is a.b.co.uk cut to b.co.uk rather than co.uk?
- Because co.uk is a place where names are sold, not a name anyone owns. Nominet registers under co.uk, so b.co.uk is the registrable domain and a.b.co.uk is a host inside it. A tool that keeps the last two labels reports co.uk here, which is both useless as an owner and wrong as a domain. The same rule covers com.au, co.jp, com.br, co.za and gov.in: the shipped table carries second-level namespaces for 107 country-code registries. Cut at the last label instead and you would get uk, which is not a domain at all.
- Why does tenant.github.io stay whole?
- GitHub asked for that boundary. The Public Suffix List has two sections: the ICANN section, which is the registries themselves, and the private section, where a platform declares that the names it hands out are separate sites. GitHub Pages is in the private section, so github.io is a public suffix and tenant.github.io is the registrable domain, exactly as browsers treat it for cookies. The table here ships 840 rules from the ICANN section and 67 from the private one, so the same is true of bucket.s3.amazonaws.com, an app on herokuapp.com, a site on pages.dev and a shop on myshopify.com. The worked rows under the stage name the rule that decided each cut, the CSV carries it for every row, and in the list a domain cut by a private rule is shown in a different colour from one cut by a registry.
- What does the shipped list cover, and what does it miss?
- It is a subset, transcribed by hand on 2026-09-21 from the Public Suffix List at publicsuffix.org, which Mozilla maintains under the Mozilla Public License 2.0. It holds 907 rules: every rule in it is one that moves the boundary, which means the multi-label, star and exception rules, the second-level namespaces of 107 country-code registries, the Canadian provinces and the United States states, and the private-section entries for the platforms people paste most. Single-label rules such as com are left out on purpose, because the default rule already cuts an unlisted name at its last label and listing them would change no answer. What it misses: the third level under a state, so school.k12.ny.us is cut here to k12.ny.us; suffixes written in a non-Latin script; the long tail of private-section platforms, whose hosts are cut at the registry boundary instead and so read one label short; and anything added to the list after the transcription date. There is no network request in this page, so nothing refreshes itself.
- How are mail addresses, ports, IP addresses and international names handled?
- By stated parser rules, in this order. A scheme such as https:// is dropped, then everything from the first slash, question mark or hash. At an at sign, whatever follows the last one is the host, so both sam@shop.example.com and https://user:pass@example.com/ give their domain. Two or more colons mean an IPv6 literal, which is rejected by name; a trailing colon and digits is a port and is dropped, so example.com:8080 is example.com while 192.0.2.10:8080 is listed as an IP address and never as a domain. A trailing dot is the DNS root and is dropped, and the host is lowered. An international name is kept in the form you pasted it: no punycode is converted in either direction, so xn--e1afmkfd.xn--p1ai and the same name in Cyrillic both come back the way they went in, and a top-level label written in a non-Latin script or beginning with xn-- is accepted without the root table.
- Why was notes.txt rejected instead of extracted?
- Because txt is not a top-level domain, and a domain extractor that reports file names is worse than useless on a page of prose. The last label is checked against a table of 663 top-level domains the page ships: every two-letter country code, the legacy and sponsored names, and the widely used new ones. A label outside it is listed under the results as an unknown top-level domain, beside the run it came from, rather than silently dropped or silently counted. Real names that look like file extensions are safe, since zip and mov are genuine top-level domains and are in the table. Ordinary prose stays quiet in a different way: a run with no dot, a run whose last label is a single character such as e.g, and a run whose last label is all digits such as 1.2.3 are passed over without a word, because they were never written as addresses. An IPv4 address is the exception to that last one: 1.2.3.4 is named as an IP address wherever it turns up.
- Can I keep the subdomains, or keep the duplicates?
- Yes to both, with the switches on the readout. Output set to Host keeps the whole host, so a.b.co.uk and shop.example.com stay as they are; set to Domain it lists b.co.uk and example.com. Duplicates set to Removed folds repeats into one row with a count and tells you how many were folded, so www.example.com and shop.example.com become one line in Domain mode; set to Kept, every occurrence stays in the order it was read. The list can be ordered as first seen, A to Z, or by how often each one appears. The Found count is how many lines the list holds and the Rejected count is how many runs were left out of it, and a run that was left out more than once says how many times beside its reason.
- How much can I paste, and does any of it leave my browser?
- One pass reads up to 1,048,576 bytes, which is 1 MB of text, and a larger paste is refused with both numbers and a note to split it, rather than scanned in part and handed back as though it were complete. Nothing is uploaded: the scan and the rules both run in this tab, there is no account, nothing is gated, and no text is sent anywhere or logged. The preview spells out the first 60 rows and the first 60 rejects, while Copy and the CSV always write every one. Your draft and the three switches are remembered in this browser alone, a paste over 100,000 bytes is read in full but not stored, and the Start over button above the tool forgets them.
- Can I get the results into a spreadsheet?
- The CSV button downloads domains.csv with one row per result and the columns value, host, public suffix, rule, occurrences, status and note. The rule column says icann, private or tld, which is which table answered, and the note repeats it in words. The rejected rows are in the same file with their reason in the status column and the full explanation in the note, so what was left out travels with what was found. Fields holding a comma or a quote are quoted the way a spreadsheet expects, and Copy puts the plain list on the clipboard instead, one value per line.
Domains are cut at the registrable boundary by a Public Suffix List subset shipped with the page, 907 rules dated 2026-09-21 and including the private section, which is why b.co.uk is one domain and tenant.github.io is another. There is no DNS lookup and no network request, so a host whose suffix is not among those rules is cut at its last label, and a top-level domain outside the 663 this page ships is listed as rejected rather than guessed. Text up to 1,048,576 bytes is read in one pass, and a longer paste is refused with both numbers rather than trimmed.