Agent skill
free-first-domain-resolver
Resolve a list of company names to verified domains for a fraction of a cent per name instead of a per-row vendor fee.
Filed under Prospecting and list building.
From jurjen-gtm-engineer/gtmskills · 55 skill entries · 0 · pushed 2026-10-04
What it does when it runs
Resolve a list of company names to verified domains for a fraction of a cent per name instead of a per-row vendor fee. Runs a cost waterfall (owned Google Maps table and Google Knowledge Graph for free, then one cheap search, then Google Places) and verifies every domain against what the page declares about itself (title, Open Graph, JSON-LD), never the SSL certificate. Refuses to guess: anything it cannot confirm is flagged \"needs review\" instead of returning a confident wrong domain. Use when someone has a CSV of company names and needs domains (the same move works for LinkedIn URLs and parent companies). Based on Jordan Crawford's free-first resolver idea (Blueprint GTM). Not for finding contact emails or enriching people.
Automated analysis of the skill and the 7 files bundled beside it. A skill’s own description is written to be selected by an agent, so it describes the job and not the dependencies.
- Keys and connectors you must supply
- GOOGLE_KG_API_KEY
- GOOGLE_PLACES_API_KEY
- SERPER_API_KEY
- Hosts it reaches
- blueprintgtm.com
- edge.blueprintgtm.com
- google.serper.dev
- kgsearch.googleapis.com
- places.googleapis.com
- Tool permissions it declares
- No
allowed-toolsin the frontmatter. It does act, so it runs under whatever permissions your session already grants. - Actions present in the files
- shellwrites filesnetwork
Install it
View source on GitHub ↗git clone --depth 1 --filter=blob:none --sparse https://github.com/jurjen-gtm-engineer/gtmskills.git /tmp/gtmskills git -C /tmp/gtmskills sparse-checkout set "skills/free-first-domain-resolver" mkdir -p ~/.claude/skills/free-first-domain-resolver cp -R "/tmp/gtmskills/skills/free-first-domain-resolver/." ~/.claude/skills/free-first-domain-resolver/
Picked up without a restart. A project skill of the same name is shadowed by your personal one. For one repository only, swap ~/.claude/skills for .claude/skills. Claude Code docs ↗
The folder is the same in every client that implements the format — 46 of them — so if yours is not above, only the destination changes.
Before you install: this skill will not complete its job on a bare agent. It needs GOOGLE_KG_API_KEY, GOOGLE_PLACES_API_KEY, SERPER_API_KEY, which you have to obtain separately.
The skill
Source on GitHub ↗Reproduced in full from jurjen-gtm-engineer/gtmskills/blob/77dc0b3112dbf6cf906dfc3d526b6f7031bf964c/skills/free-first-domain-resolver/SKILL.md, which is licensed MIT (repository). 997 words, 12 headings.
Free-First Domain Resolver
Company name to domain for a whole list: cheapest source first, verified, with a hard refusal instead of a guess. The idea comes from Jordan Crawford's On the Edge (edge.blueprintgtm.com). The code and the thresholds here are our own build.
Why this exists. Per-row vendors charge per lookup and do not check the answer. Most rows clear on free sources, and every domain can be verified against the site itself. A wrong domain is worse than a blank: a human fixes a blank in a minute, while a confident wrong domain poisons every later step. So this tool refuses when it is not sure.
The waterfall (stop on first CONFIRMED)
| Tier | Source | Cost | Notes |
|---|---|---|---|
| 0 | Existing domain on the row | free | a candidate to verify, not to trust |
| 1 | Owned local table (a Google Maps export you already have) | free | small-business tail, plus the phone that pins geography |
| 2 | Google Knowledge Graph API | free within its daily quota | returns the official site for companies Google knows |
| 3 | Serper (one Google search) | a fraction of a cent | pull the candidate, let verification throw out the rest |
| 4 | Google Places Text Search | a fraction of a cent | new or non-US companies not in the owned table; returns website and phone |
| 5 | Model judge (semantic remainder only) | sub-agents | parent vs subsidiary, rebrand, directory vs official. Most rows never reach it |
Every tier costs more than the one above it, and most of a list clears in tiers 1 and 2. Check the live price pages before a big run; prices change.
Spend rule: free when it is right and fast, a fraction of a cent when that makes it sure, never a flat vendor fee for work the website will confirm.
Verification: ask the page, not the certificate
The Python pipeline fetches each candidate (deterministic: requests plus an HTML parse) and scores page-declared identity:
<title>, Open Graphog:site_nameandog:titlename match: the free signal that fires most often- JSON-LD
Organization(name plussameAsLinkedIn or Wikipedia): strong corroboration - DNS and MX liveness: a real running business
- phone and address: the geographic confirmer (which "Riverside Dental")
- redirects followed to the final domain (
gong.comtogong.io)
Never the SSL certificate. It is often blank on brands and always uninformative on free certificates. It names the issuer, not the owner.
How to run
cd skills/free-first-domain-resolver
python3 -m pip install -r requirements.txt
# 1. (once) build the owned free table from a Google Maps export
python3 scripts/build_owned_table.py --input ~/data/google_maps_export.csv --db data/owned.sqlite
# 2. resolve a list. Input CSV needs a name column; zip, city, phone and domain are optional.
python3 scripts/resolve.py \
--input companies.csv --output resolved.csv \
--name-col company --zip-col zip --owned-db data/owned.sqlite
resolve.py writes three files next to --output:
resolved.csv: every row plusresolved_domain, status, source_tier, confidence, signals, phoneresolved.needs_review.csv: nothing could confirm, a human fixes theseresolved.ambiguous.csv: the name matched but there are several live candidates or a parent vs subsidiary question. This goes to the model tier
API keys (environment variables, all optional)
GOOGLE_KG_API_KEY: Knowledge Graph Search API (enable it on your Google Cloud project first)SERPER_API_KEY: Serper.dev (tier 3)GOOGLE_PLACES_API_KEY: Places Text Search (tier 4)
With zero keys it still runs tiers 0 and 1 plus verification. Rows that need search land in needs_review.
The model tier (sub-agents, not a model call from Python)
After resolve.py, spawn sub-agents of your coding agent over resolved.ambiguous.csv only. For each ambiguous row give the sub-agent the name, the live candidates and the page-declared identity for each, and ask it to pick the official domain or return needs_review. Default to needs_review when uncertain. Batch about 25 rows per sub-agent. This is the only expensive tier and most rows never reach it.
Calibration
The defaults are explicit and tunable. They live in references/calibration.md and scripts/calibration.py:
- Short-circuit: a source that knows the domain, the page agrees, not disqualified: accept, no model.
- Name match: strong at 85 or more, maybe from 60 to 84, reject under 60 (token-set ratio), with a generic-name guard (a common name needs a corroborator: phone, address or
sameAs). - Geographic escalation: doubt about which location is settled by a Places phone match.
- CONFIRMED needs a strong name match AND at least one corroborator AND no disqualifier. Anything else is
needs review.
Tune these on a hand-labeled slice before you trust a big run.
Discipline (do not skip)
- Never emit a guess. No confirmation means
needs review. - Verify against the page, never the certificate.
- Own the data, do not rent each lookup. Build the owned table from your own Google Maps scrape, and do not redistribute data files you bought or were given.
- Log what you dropped. If a run skips a tier (missing key, rate limit), say so in the summary. Silent truncation reads as "covered everything".
- The same move resolves LinkedIn URLs, parent companies and rebrands. Verify, do not buy.
Files
scripts/resolve.py: orchestrator and CLI (the waterfall and the bucketing)scripts/sources.py: discovery tiers (existing, owned table, Knowledge Graph, Serper, Places)scripts/verify.py: page-declared-identity verification, DNS, redirects, disqualifiersscripts/calibration.py: thresholds, generic-name list, directory and government blacklistscripts/build_owned_table.py: builds the free local table from a Google Maps exportreferences/calibration.md: the thresholds, explainedrequirements.txt
Credits
The free-first waterfall, "verify against the page, not the certificate" and "refuse instead of guess" are Jordan Crawford's ideas, published in On the Edge by Blueprint GTM. He ships his own installed tool with his own tuned thresholds. This is an independent build with our own defaults. For a Google Maps export, see the list-building skills in coldoutboundskills by Growth Engine X.
Files bundled with it
These load only when the skill asks for them, so they cost nothing until it runs.
Other skills for the same job
Different authors, same problem. Matched on the words in the skill name, across every library in the catalogue except this one.
- free-tools by coreyhaines31 · 53,460
- playbook-first-name-cleaning by growthenginenowoslawski · 739
- zapmail-domain-setup-public by growthenginenowoslawski · 739
- domain-research by OpenClaudia · 708
- domain-expired-opportunity-finder by Varnan-Tech · 672
- copywriting-first-touch by Othmane-Khadri · 317
- time-to-first-value by AIDevGTM · 310
- first-50-users by AIDevGTM · 310
Need help setting it up?
This page tells you what free-first-domain-resolver does and what it needs. Cheetah builds the agent setup it runs inside: data, CRM, sequencing and the guardrails.
Book a call →The directory stays free. There is nothing gated behind this.