ScrapeField

Google Maps scraper API

Search for places, then read their details, reviews and photos — with the field names Google’s own Places API uses. Blocks handled; nothing for you to unblock.

Endpoints
4
From
2 credits a call
Returns
place, review, photo
google.com/maps/place/

Blue Door Coffee

4.4(1,921)
Bakery · $$
DirectionsSaveNearbyShare
  • 124 Franklin St, Brooklyn, NY 11249, United States
  • Open · Closes 7 PM
  • bluedoorcoffee.example
  • (718) 555-0120

The same page, from the API sample data

  1. 1name "Blue Door Coffee"
  2. 2rating 4.4user_ratings_total 1921
  3. 3category "Bakery"price_level 2
  4. 4formatted_address "124 Franklin St, Brooklyn, NY 11249, United…
  5. 5opening_hours.weekday_text[0] "Monday: 7:00 AM – 7:00 PM"
  6. 6website "https://bluedoorcoffee.example"
  7. 7formatted_phone_number "(718) 555-0120"
  8. +place_id "ChIJN1t_tDeuEmsRUsoyG83frY4"business_status "OPERATIONAL"claimed falsein the response, not on the page

Try it now

Every Google Maps endpoint, as an MCP tool, as a REST call, or as a question in plain English. Each one runs against the live API in demo mode — no key, no account.

POSThttps://scrapefield.com/mcp
4 tools
Transport
HTTP, JSON-RPC 2.0
Methods
initialize · tools/list · tools/call
Auth
Bearer key — or none, for demo mode
claude mcp add --transport http scrapefield https://scrapefield.com/mcp
Runs against the live server. No key, no account.
// press Call — the server lists its 4 tools,
// each with the schema an agent reads before calling it

What people build with it

Three worked examples, each with the calls it makes and what a run costs — multiplied out from the published price of every call.

01

Build a lead list for a city

Search a category neighbourhood by neighbourhood and every result already carries its phone, website, rating and opening hours — no second call per business. Duplicates across neighbourhoods collapse on the place_id.

GET google-maps/places× 515 cr
per run, up to 100 businesses15 cr

≈ $0.009 at the 250k pack

const API = 'https://api.scrapefield.com/v1';
const sf = (path, q) =>
  fetch(API + '/' + path + '?' + new URLSearchParams(q), {
    headers: { Authorization: 'Bearer ' + process.env.SCRAPEFIELD_KEY },
  }).then((r) => r.json());

const areas = ['Alfama', 'Baixa', 'Chiado', 'Estrela', 'Belém'];
const leads = new Map();

for (const area of areas) {
  const query = 'coffee shops in ' + area + ', Lisbon';
  const { data } = await sf('google-maps/places', { query, limit: 20 });
  for (const p of data) {
    leads.set(p.place_id, {
      name: p.name,
      phone: p.international_phone_number,
      website: p.website,
      rating: p.rating,
      reviews: p.user_ratings_total,
    });
  }
}

console.table([...leads.values()]);
02

Hear about a bad review the day it lands

Check the newest reviews at each of your locations once a day and raise anything at two stars or below — with whether the owner has already replied, so nobody answers twice.

GET google-maps/reviews× 1,5004,500 cr
a month, 50 locations checked daily4,500 cr

≈ $2.68 at the 250k pack

const API = 'https://api.scrapefield.com/v1';
const sf = (path, q) =>
  fetch(API + '/' + path + '?' + new URLSearchParams(q), {
    headers: { Authorization: 'Bearer ' + process.env.SCRAPEFIELD_KEY },
  }).then((r) => r.json());

const since = Date.now() - 24 * 3600 * 1000;

for (const place_id of myLocations) {
  const q = { place_id, sort: 'newest', limit: 20 };
  const { data } = await sf('google-maps/reviews', q);
  const bad = data.filter(
    (r) => Date.parse(r.publish_time) > since && r.rating <= 2,
  );

  for (const r of bad) {
    const replied = r.owner_response ? 'already answered' : 'no reply yet';
    notify(place_id, r.rating, r.text, replied);
  }
}
03

Map a market before you enter it

Lay a grid over a city and search around each point, so no part of it is missed by a 20-result ceiling. Group what comes back by category and you have ratings, review counts and price levels, street by street.

GET google-maps/places× 2575 cr
one city centre, a 5 × 5 grid75 cr

≈ $0.045 at the 250k pack

const API = 'https://api.scrapefield.com/v1';
const sf = (path, q) =>
  fetch(API + '/' + path + '?' + new URLSearchParams(q), {
    headers: { Authorization: 'Bearer ' + process.env.SCRAPEFIELD_KEY },
  }).then((r) => r.json());

const seen = new Map();

for (let i = 0; i < 5; i++) {
  for (let j = 0; j < 5; j++) {
    const lat = 38.70 + i * 0.009;
    const lng = -9.17 + j * 0.0115;
    const q = { query: 'restaurant', lat, lng, radius_m: 700 };
    const { data } = await sf('google-maps/places', q);
    for (const p of data) seen.set(p.place_id, p);
  }
}

const places = [...seen.values()];
const byCategory = Object.groupBy(places, (p) => p.category);

Everything that comes back

The complete response behind the Google Maps view at the top of this page, from GET /v1/google-maps/place — every field, including the ones that are null. Fields are named after Google's Places API, so if you have read those docs you already know them. Every field of google_maps_place, google_maps_review and google_maps_photo is documented.

{
  "data": {
    "place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
    "name": "Blue Door Coffee",
    "category": "Bakery",
    "categories": [
      "Bakery",
      "Bicycle shop"
    ],
    "formatted_address": "124 Franklin St, Brooklyn, NY 11249, United States",
    "address": {
      "street": "124 Franklin St",
      "city": "Brooklyn",
      "region": "New York",
      "postal_code": "11249",
      "country_code": "US"
    },
    "location": {
      "lat": 40.66704,
      "lng": -73.927703
    },
    "plus_code": "TNNG+EP",
    "rating": 4.4,
    "user_ratings_total": 1921,
    "rating_distribution": {
      "1": 56,
      "2": 75,
      "3": 157,
      "4": 458,
      "5": 1175
    },
    "price_level": 2,
    "formatted_phone_number": "(718) 555-0120",
    "international_phone_number": "+1 718-555-0120",
    "website": "https://bluedoorcoffee.example",
    "url": "https://www.google.com/maps/place/?q=place_id:ChIJN1t_tDeuEmsRUsoyG83frY4",
    "business_status": "OPERATIONAL",
    "opening_hours": {
      "weekday_text": [
        "Monday: 7:00 AM – 7:00 PM",
        "Tuesday: 7:00 AM – 7:00 PM",
        "Wednesday: 7:00 AM – 7:00 PM",
        "Thursday: 7:00 AM – 7:00 PM",
        "Friday: 7:00 AM – 7:00 PM",
        "Saturday: 9:00 AM – 7:00 PM",
        "Sunday: 9:00 AM – 7:00 PM"
      ],
      "periods": [
        {
          "open": {
            "day": 0,
            "time": "0900"
          },
          "close": {
            "day": 0,
            "time": "1900"
          }
        },
        {
          "open": {
            "day": 1,
            "time": "0700"
          },
          "close": {
            "day": 1,
            "time": "1900"
          }
        },
        {
          "open": {
            "day": 2,
            "time": "0700"
          },
          "close": {
            "day": 2,
            "time": "1900"
          }
        },
        {
          "open": {
            "day": 3,
            "time": "0700"
          },
          "close": {
            "day": 3,
            "time": "1900"
          }
        },
        {
          "open": {
            "day": 4,
            "time": "0700"
          },
          "close": {
            "day": 4,
            "time": "1900"
          }
        },
        {
          "open": {
            "day": 5,
            "time": "0700"
          },
          "close": {
            "day": 5,
            "time": "1900"
          }
        },
        {
          "open": {
            "day": 6,
            "time": "0900"
          },
          "close": {
            "day": 6,
            "time": "1900"
          }
        }
      ]
    },
    "popular_times": [
      {
        "day": 0,
        "busyness": [
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          23,
          55,
          94,
          100,
          90,
          83,
          75,
          62,
          33,
          13,
          7,
          1,
          0,
          0,
          0,
          0,
          0
        ]
      },
      {
        "day": 1,
        "busyness": [
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          18,
          45,
          71,
          83,
          72,
          66,
          61,
          46,
          29,
          14,
          4,
          3,
          0,
          0,
          0,
          0,
          0
        ]
      },
      {
        "day": 2,
        "busyness": [
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          17,
          47,
          74,
          78,
          71,
          63,
          65,
          52,
          28,
          11,
          8,
          3,
          0,
          0,
          0,
          0,
          0
        ]
      },
      {
        "day": 3,
        "busyness": [
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          21,
          42,
          74,
          84,
          73,
          65,
          63,
          52,
          26,
          14,
          10,
          2,
          0,
          0,
          0,
          0,
          0
        ]
      },
      {
        "day": 4,
        "busyness": [
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          18,
          48,
          75,
          84,
          74,
          63,
          66,
          47,
          26,
          13,
          4,
          3,
          0,
          0,
          0,
          0,
          0
        ]
      },
      {
        "day": 5,
        "busyness": [
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          23,
          56,
          94,
          100,
          86,
          83,
          77,
          64,
          37,
          17,
          5,
          3,
          0,
          0,
          0,
          0,
          0
        ]
      },
      {
        "day": 6,
        "busyness": [
          0,
          0,
          0,
          0,
          0,
          0,
          0,
          23,
          55,
          90,
          100,
          84,
          78,
          77,
          63,
          32,
          18,
          6,
          1,
          0,
          0,
          0,
          0,
          0
        ]
      }
    ],
    "about": {
      "service_options": [
        "Dine-in",
        "Takeout"
      ],
      "accessibility": [
        "Wheelchair accessible entrance"
      ],
      "payments": [
        "Credit cards",
        "Debit cards",
        "NFC mobile payments",
        "Cash"
      ]
    },
    "claimed": false,
    "photo": {
      "url": "https://cdn.example/maps/KccUhk3IwEeL5pn7.jpg",
      "width": 4032,
      "height": 3024,
      "author_name": null,
      "author_url": null
    }
  },
  "meta": {
    "request_id": "req_7f3ac1e94b2d40f8a1c6e5d2",
    "credits_charged": 3,
    "credits_remaining": 74218,
    "cached": false,
    "fetched_at": "2026-09-20T09:12:03Z",
    "next_cursor": null
  }
}

Endpoints and prices

One published credit cost per endpoint, charged per call and refunded automatically when a call fails. See what a credit costs.

Google Maps, specifically

The questions people ask about this platform before they call it.

How is this different from the Google Places API?
The Places API is Google’s own, official product, and the right choice inside a user-facing app where its licence matters. We return what the public Maps page shows — including what the Places API leaves out, like popular times and the rating breakdown — under the field names the Places API uses, at one published credit cost per call.
How many results does a search return?
Up to 20 per call, and the next page is one call away with meta.next_cursor. To cover a whole city, search around points with lat, lng and radius_m (100 m to 50 km) — the market recipe above does exactly that.
Can I get every review of a place?
Reviews come 20 per call, ordered by relevance, newest, highest or lowest, and you page through them with meta.next_cursor. Each has the rating, the text, the author, the date, any photos, and the owner’s reply where there is one.
Do you store the photos?
No. google-maps/photos returns the image URLs on the platform’s own CDN, with their dimensions. We do not rehost images.
How fresh is the data?
Places are cached for 24 hours and reviews for 6. Pass fresh=true to fetch now instead; it is charged the same, and needs credits you have bought rather than the free ones. A failed call is refunded automatically.

The same key, three more platforms

One key, one balance and one invoice across all four — and each platform’s data in its own shape, because they are four different systems.

Your first Google Maps call, in a minute

Get a key