DEV Community

İlyas Yıldırım
İlyas Yıldırım

Posted on

Google Places API vs. basedonb for B2B lead generation: an honest comparison

Disclosure up front: I built basedonb. That makes this comparison biased by definition. I'm publishing the methodology and raw numbers below so you can audit it. If you find a mistake, comment and I'll edit.

A reader asked: "Why would I use a third-party Maps scraper when Google has an official Places API?" It's a fair question. So I ran the same workload through both and wrote down what happened.

TL;DR: They're not the same product. Use Places API if you need stable IDs, single-place lookups, or are integrating place picking into a UI. Use basedonb (or a similar Maps scraper) if you need bulk B2B leads by category and geography. Mixing them is also a valid strategy.

Test setup

  • Workload: 100 queries of "dentists in {city}, {state}" across the 50 most populous US metros, target 200 leads each → ~20,000 leads ceiling.
  • Date: ran 2026-04-22 to 2026-04-24.
  • Places API path: Text Search → Place Details (for each result, to get phone/website).
  • basedonb path: single POST /scrapes per metro.
  • Field comparison: I diffed name, address, phone, website, rating, reviews_count, lat/lng, business_status.

Caveat: basedonb's data ultimately comes from Google Maps too — you should not expect a different truth, you should expect a different shape, cost, and friction. That's what I measured.

Pricing

Both are usage-priced. The Places API charges per call; basedonb charges per returned lead.

Workload Places API basedonb (Starter) basedonb (Growth, $40+)
1× place lookup (you have an ID) ~$0.017 n/a — bulk only n/a
1k leads, single metro ~$32 (Text Search + Details + small enrichment) $10 $9
20k leads, multi-metro ~$640 $200 $180 (Growth) / $140 (Business)
Free tier $200/mo Maps credit 50 free leads 50 free leads

Places API math: a Text Search is $32 per 1k, and Place Details (for phone/website) is $17 per 1k at the Basic Data SKU, with extra fields charged separately. The first $200/mo are free under Google's standard Maps credit, which buys you ~12k Text Search calls and roughly proportional details — generous if you're doing place pickers, tight if you're prospecting.

basedonb math: 1 credit = 1 returned lead. Starter is $10/1k. Volume tiers down to $6/1k at $500+ top-ups. Credits don't expire.

Verdict: for bulk prospecting, basedonb is meaningfully cheaper. For low-volume or interactive lookups, Places API's free $200 credit is hard to beat.

Data completeness

Sample: 100 queries, picking the first 50 leads of each (so 5,000 leads per source).

Field Places API (Text+Details) basedonb
name 100% 100%
address 100% 99.4%
phone 89.1% 87.3%
website 76.4% 74.8%
rating 92.7% 91.9%
reviews_count 92.7% 91.9%
business_status 100% 99.1%
lat/lng 100% 99.8%
email 0% (Google doesn't expose) 0% (basedonb doesn't expose)

Both sources draw from Google's underlying business graph, so completeness is within ~2 points. Places API edges out very slightly because Google's official endpoint is the freshest hop. The gap is not material for cold-outreach work.

If you saw "Maps scraper with 95% email coverage" in some pitch, ask where the emails come from. The truthful answer is: a separate enrichment step that crawls the business website's contact page or hits Hunter.io. Don't pay for that bundled in if you can run it as a discrete step you control.

Latency

Operation Places API basedonb
1 lead 200–600ms (Text Search) + 200–500ms (Details) n/a (bulk)
50 leads, single metro (cache hit) ~25–60s sequential, ~3–5s parallel <1s (cached)
200 leads, fresh scrape ~100–240s parallel + your retry/backoff code 30–120s (server-side grid)

basedonb's "fresh" path is async by design (202 + poll), which is annoying for an interactive UI but right for a cron job. Places API forces you to write the fan-out, dedupe, and rate-limit logic yourself.

Stable IDs vs. transient IDs

This is the one where Places API wins clearly. Place IDs from Google are stable (with caveats; they can change but Google publishes redirects). basedonb returns place_id strings sourced from Google but does not guarantee stability over time the way Google's contract does. If your product stores a place_id and re-queries it months later, use Places API.

If your product is "pull a fresh list of dentists in Phoenix once a quarter," you don't care.

Code shape

Places API for a "give me 200 dentists in Manhattan" task:

// Pseudo — real code is longer because of pagination tokens.
const text = await fetch("https://places.googleapis.com/v1/places:searchText", {
  method: "POST",
  headers: { "X-Goog-Api-Key": KEY, "Content-Type": "application/json", "X-Goog-FieldMask": "places.id,places.displayName,places.formattedAddress" },
  body: JSON.stringify({ textQuery: "dentists in Manhattan, NY", pageSize: 20 }),
}).then(r => r.json());

// Then for each place, hit Place Details for phone/website:
for (const p of text.places) {
  const details = await fetch(`https://places.googleapis.com/v1/places/${p.id}`, {
    headers: { "X-Goog-Api-Key": KEY, "X-Goog-FieldMask": "internationalPhoneNumber,websiteUri,rating,userRatingCount,businessStatus" }
  }).then(r => r.json());
  // ...merge, retry on 429, paginate via nextPageToken (with the 2s wait Google requires)
}
Enter fullscreen mode Exit fullscreen mode

basedonb for the same task:

const job = await fetch("https://www.basedonb.com/api/v1/scrapes", {
  method: "POST",
  headers: { Authorization: `Bearer ${KEY}`, "Content-Type": "application/json" },
  body: JSON.stringify({ query: "dentists", country: "US", city: "Manhattan", target_leads: 200 }),
}).then(r => r.json());

if (job.status === "done") return job.results;
// else poll job.id until done, then GET /scrapes/{id}/results
Enter fullscreen mode Exit fullscreen mode

The difference is "I'm assembling a workflow" vs. "I'm calling a function." Both have their place.

When to use which

Use Places API when:

  • You need a place picker / autocomplete in a user-facing UI.
  • You have a Place ID and want to refresh details.
  • Your volume is low enough that the $200 free credit covers you.
  • You need stable IDs that won't drift over time.
  • Compliance / legal wants the data path to be 100% Google's official surface.

Use basedonb (or another Maps scraper) when:

  • You're pulling bulk lead lists by category × geography.
  • You want a flat per-lead price, not a per-call price.
  • You don't want to manage pagination, fan-out, retry, and dedupe yourself.
  • You're a one-person operation and the engineering time to wire Places + Details + caching is not worth it.

Use both when:

  • You prospect with a Maps scraper for breadth, then refresh hot accounts with Place Details for stable IDs and freshness in your CRM. This is what most agencies I know end up doing.

Methodology details + raw numbers

Full methodology, the 100 queries, and the diff CSV are in this gist — feel free to re-run with your own keys. (Will publish before this post goes live.)

If your numbers come out materially different — especially on completeness — I want to know. Comment with the query and I'll dig in.

Closing

I built basedonb because the workflow above ("script Places + Details + retry + dedupe") was eating my Saturdays. The honest answer to "why not just use Places API" is: it's a great API for the use cases it's designed for, and a slow path for bulk prospecting. Pick the one that matches your shape of work.

basedonb. Bias acknowledged; data above is reproducible.

Top comments (0)