Have an agent build it. Copy the brief below into Claude Code, Cursor, or any coding agent with access to your project. It states the calls, the questions worth asking you first, and the mistakes to avoid.
Agent brief
Agent brief
Start with an honest base list
Before the pipeline, decide where the universe of businesses comes from. Map products are not scrapeable. Their terms forbid it and the results live inside an interactive pane rather than on a page, so anyone offering you a map scrape is selling you a liability rather than a dataset. Use the licensed route: a places API with a category and a radius, or OpenStreetMap through Overpass for an open licensed alternative. Both give you names and approximate locations, and both stop well short of a usable record. That is the split worth understanding. A licensed places source gives you the spine. This pipeline gives you the record.The pipeline
1. Find each business’s own site
search reaches past the aggregators to the pages the businesses publish themselves.
"scrapeResults": true when you want each result’s content in the same call. That bills 1 credit per result on top of the search, so leave it off while you are still deciding which results are worth keeping.
2. Enumerate every branch of a multi-location business
Most categories are dominated by a handful of chains with dozens or hundreds of locations each. Search will show you one branch.map gives you all of them.
search filter is a substring match against the URLs, so a city name or a path segment narrows a national site down to one region without fetching anything. This is the step where coverage actually gets built: one call, one credit, and the long tail of branches no directory bothered to list.
Raise limit when the result comes back exactly at the number you asked for, because that means you hit your ceiling rather than the end of the list.
3. Turn each page into a record
One schema, written once, applied across operators whose sites have nothing structurally in common.homeCollection is the field to pay attention to. It is meaningless outside diagnostics, and that is the point: the last field in the schema is usually the one specific to your category, and it is the reason to write a schema rather than buy a list. A dealership directory wants brandsSold, a gym wants openTwentyFourHours, a clinic wants the specialisms. No aggregator carries any of them, because no aggregator knows which vertical you are in.
urls takes a list, so a batch of branches is one call rather than one call per branch.
Deduplicate before you extract, not after
Extraction is the priced step, so paying for it twice on the same location is the easiest money to waste here. The same branch is routinely reachable from several URLs: a city landing page, a locality page, a legacy path kept alive for search. Normalise the list first, meaning drop tracking parameters, settle on one trailing slash convention, and collapse obvious aliases. Then, after extraction, deduplicate again on the record itself, because two genuinely different URLs can describe one physical location. A phone number plus a postal code is a stronger key than a name. Names carry franchise suffixes, punctuation and spelling drift that no normalisation fully fixes.Keeping it current
Local business data goes stale faster than almost anything else. Branches open, move, change hours and quietly close. Re-runmap on a schedule, since it is 1 credit and the diff is most of the value. A URL that appeared is a new branch. A URL that disappeared is a closure or a redesign, and either way it is the signal you wanted.
Re-extract selectively. Hours and services change; addresses rarely do. Extract new URLs always and cycle through existing ones slowly, rather than re-running the whole city every week.
Mark what left rather than deleting it. A directory that silently drops a closed location cannot tell you it closed, and that is often the question being asked.
What it costs
Search and map are 1 credit each. Extract is 5 credits per URL, because it is model-backed work rather than a fetch. A worked example: one operator, 200 branches in a city, full records. That is 1 credit to map and 1,000 to extract. Repeat it for the three or four operators that cover most of a category and you have the city, with fields no directory sells. For thousands of pages, usebatch rather than looping extract calls. It takes the same options, returns a job id, and calls a webhook when it finishes, so nothing sits waiting on a response.
Failed calls never cost credits, so the cheapest way to size any of this is to run step one and look at what comes back.