Enterprise Domain Mapper
Map enterprise corporate structures to enrichable domains. Feed it company names, get back subsidiaries, acquisitions, and regional domains that your enrichment tools are missing.
Every sales team doing enterprise ABM hits the same wall: large companies have dozens of subsidiaries, acquisitions, and regional entities, each with their own email domain. Without a complete domain map, tools like Clay and Apollo only find contacts at the parent domain. Entire business units get missed.
This tool fixes that.
$ domain-mapper "HSBC" --domain hsbc.com --verify-dns
HSBC
├── · Hang Seng Bank hangsengbank.com [Name guess] resolves (no MX)
├── ✓ HSBC Bank Middle East hsbcbankmiddleeast.com [Name guess] ✓ MX verified
├── ✓ HSBC UK hsbc.co.uk [TLD guess] ✓ MX verified
├── ✓ HSBC Bank Hong Kong hsbc.com.hk [TLD guess] ✓ MX verified
├── ✓ HSBC Bank Australia hsbc.com.au [TLD guess] ✓ MX verified
├── ✓ HSBC Bank India hsbc.co.in [TLD guess] ✓ MX verified
└── ✓ HSBC Bank Malaysia hsbc.com.my [TLD guess] ✓ MX verified
Found 14 subsidiaries, 52 domains (52 guessed, 6 MX verified)
The tree above is abridged: the run generates 52 candidate domains and six of them
have live mail. Pass --output results.csv to get all of them with their sources
and confidence.
The problem
Enterprise accounts don't operate under a single domain. A company like HSBC runs distinctly branded subsidiaries such as First Direct alongside regional banks in dozens of countries, each with its own domain. Deloitte has member firms. Nestlé sits over hundreds of consumer brands that use completely different domains.
If you're running enrichment against just hsbc.com, you're finding maybe 30% of the contacts you could be reaching. The rest are hiding behind firstdirect.com, hsbc.co.uk, hsbc.com.hk, and domains you didn't know existed.
Building these domain maps manually takes hours per account. We built this tool because we got tired of doing it by hand.
Quick start
Installation
pip install enterprise-domain-mapper
Or clone and install locally:
git clone https://github.com/gtmlayer/enterprise-domain-mapper.git
cd enterprise-domain-mapper
pip install -e .
Single company lookup
domain-mapper "Boeing"
Pass the parent domain when you know it. Regional TLD guessing builds from that stem,
so without it you get subsidiary names and .com guesses but no hsbc.co.uk:
domain-mapper "HSBC" --domain hsbc.com --verify-dns
In batch mode the domain column supplies this per row, so --domain is not needed.
Batch mode (CSV input)
domain-mapper accounts.csv --output results.csv
Your input CSV just needs a column with company names. The tool auto-detects columns named company_name, company, name, or account. If you have a domain column (domain, website, url), it'll use that as the parent domain for TLD guessing.
With DNS verification
domain-mapper accounts.csv --output results.csv --verify-dns
This checks whether guessed domains actually have mail infrastructure (MX records) or at minimum resolve (A records). Adds a few seconds per company but filters out the noise.
What it does
The tool combines three data sources and a verification layer to build comprehensive domain maps:
1. SEC EDGAR Exhibit 21 scraper
For US-listed companies, SEC filings include Exhibit 21: a legally required list of all subsidiaries. The tool looks up the company's CIK, finds the latest 10-K filing, and parses the subsidiary list with jurisdictions.
This is the highest-quality source - it's legally mandated disclosure, so it's comprehensive and current.
2. Wikipedia corporate structure parser
For non-US companies (or supplementary data), the tool searches Wikipedia for the company page and extracts subsidiary and acquisition data from infoboxes and structured sections.
Covers companies globally, though data depth varies by how well-maintained the Wikipedia page is.
3. TLD pattern generator
Once subsidiaries are identified with their jurisdictions, the tool generates likely domain patterns. A subsidiary in Italy with parent domain hsbc.com produces guesses like hsbc.it. Covers 70+ countries with their standard corporate TLD patterns (e.g. UK produces co.uk and .uk, Japan produces co.jp and .jp).
4. DNS verification (optional)
MX record lookup with A record fallback to confirm guessed domains actually resolve. A records confirm the domain exists even without mail setup.
Two limits worth knowing, because both used to produce false confidence:
- An MX record is not always mail. Registrars and parking pages publish a null MX (RFC 7505
., orlocalhost, or0.0.0.0).luxembourg.comandunitedkingdom.comboth do. Those are treated as no mail at all. - Mail is not ownership. A guessed domain with live mail proves somebody owns it, not that the company you asked about does. So a guess is capped at
Mediumhowever well it resolves.
Output format
Detailed output (default)
Ten columns, one row per subsidiary-domain pair:
| Column | Description |
|---|---|
parent_company |
The company you looked up |
parent_domain |
Known parent domain |
subsidiary_name |
Name of the subsidiary or entity |
subsidiary_type |
Subsidiary, acquisition, division, etc. |
jurisdiction |
Country or region |
domain |
Known or guessed domain |
domain_source |
Where it came from (SEC EDGAR, Wikipedia, TLD guess, Name guess) |
dns_verified |
True only when the domain has MX (mail) records |
dns_status |
DNS result: mx, a-only (resolves but no mail), unresolved, or blank if not checked |
confidence |
High = the domain came from a source (a filing or an article); Medium = a guess with live mail, or an unverified name guess; Low = an unverified regional guess. A guessed domain never reaches High on DNS alone, because mail on chaseuk.com proves a stranger parked it, not that Chase owns it |
Clay import format
One row per company with domains consolidated into a single field, ready for direct import into Clay as a data source.
domain-mapper accounts.csv --output results.csv --format clay
Importing into Clay
- Run the tool with
--format clayto get the Clay-optimised output - In Clay, create a new table or add to an existing one
- Import the CSV - the columns map directly to Clay's expected format
- Use the domain list column with Clay's enrichment tools to find contacts across all mapped domains
This is the workflow that sparked the whole tool. We were manually building domain maps for a client's enterprise accounts and realised the process was repeatable enough to automate.
Example
The examples/ directory contains input_sample.csv with five test companies to get you started:
domain-mapper examples/input_sample.csv --output examples/results.csv --verify-dns
Contributing
Want to add a new data source? The architecture makes it straightforward:
- Create a new module in
src/domain_mapper/sources/ - Implement a class with a
get_subsidiaries(company_name)method that returns a list of subsidiary objects - Add it to the orchestrator in
mapper.py - Write tests in
tests/
Some data sources we'd love to see contributed:
- Companies House (UK company registry)
- OpenCorporates API
- Crunchbase (acquisitions data)
- D&B corporate hierarchies
Pull requests welcome. Run ruff check and black before submitting, and make sure pytest passes.
Tech stack
- Python 3.10+
requestsandbeautifulsoup4for web scrapingclickfor the CLIrichfor terminal output- No paid APIs, no API keys required
Built by GTM Layer
GTM Layer builds revenue systems for B2B sales teams. We work with companies on CRM architecture, enrichment pipelines, signal-driven outbound, and everything in between.
This tool came out of real client work - we built it to solve a problem we kept hitting on enterprise ABM engagements. If you're running into similar challenges, get in touch.
Licence
MIT - use it however you want.
Metadata
Release files for enterprise-domain-mapper 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| enterprise_domain_mapper-0.2.1.tar.gz | 37.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| enterprise_domain_mapper-0.2.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 66.8 kB
Release files / enterprise_domain_mapper-0.2.1.tar.gz
| Download URL | enterprise_domain_mapper-0.2.1.tar.gz |
|---|---|
| Size | 37.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1defebd9e09d4672d6ed9a408ddc8892f8711316d4ef8c9ce7dd4126b64117f4
|
|
BLAKE2b-256 checksum How to use checksums |
b2463d743c0820a0d2f8cdb1ad86c105c8e5c9d3eda72525c4dcdc8d465b0a71
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|
Release files / enterprise_domain_mapper-0.2.1-py3-none-any.whl
| Download URL | enterprise_domain_mapper-0.2.1-py3-none-any.whl |
|---|---|
| Size | 29.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
82f0081b469f2ea366867f24c8a2ebefe5abad7c60ad2d3d85c19323979f23fe
|
|
BLAKE2b-256 checksum How to use checksums |
34f71e9ce91ea277355cba2a2b4863e7dcfef5faf13e7545dd2a9a662f887f00
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.9.6
|