Tutorial

How to Batch Export Google Maps Data to CSV

Export local business data across multiple categories and cities to CSV using the Scavio API. Automate lead list generation without manual Maps scraping.

Building lead lists from Google Maps is a core workflow for local agencies, franchise prospectors, and B2B sales teams. The manual process -- searching one category in one city, copying results, repeating -- does not scale past a handful of markets. The Scavio API accepts Google Maps queries and returns structured JSON with business name, address, phone, rating, review count, and website. This tutorial shows how to loop through a matrix of categories and cities, collect all results, and write them to a single CSV file ready for CRM import or outreach tooling.

Prerequisites

  • Python 3.8 or higher installed
  • requests and csv modules (csv is in the standard library)
  • A Scavio API key from scavio.dev
  • A list of target categories and cities

Walkthrough

Step 1: Define the category and city matrix

Create two lists representing the categories and cities you want to cross-query. The script will search every combination.

Python
categories = ["plumber", "electrician", "hvac contractor"]
cities = ["Austin TX", "Denver CO", "Portland OR"]

Step 2: Query Google Maps for each combination

POST to the Scavio search endpoint with platform set to google_maps and the query combining category and city. Collect all local_results into a flat list.

Python
import os
import requests

API_KEY = os.environ.get("SCAVIO_API_KEY", "your_scavio_api_key")
ENDPOINT = "https://api.scavio.dev/api/v1/search"

all_results = []
for category in categories:
    for city in cities:
        query = f"{category} in {city}"
        response = requests.post(
            ENDPOINT,
            headers={"x-api-key": API_KEY},
            json={"query": query, "platform": "google_maps"}
        )
        data = response.json()
        for biz in data.get("local_results", []):
            biz["search_category"] = category
            biz["search_city"] = city
            all_results.append(biz)
        print(f"{query}: {len(data.get('local_results', []))} results")

Step 3: Write results to CSV

Use the csv module to write all collected business records to a file. Include columns for name, address, phone, website, rating, review count, and the search metadata.

Python
import csv

fields = ["search_category", "search_city", "title", "address", "phone", "website", "rating", "reviews"]
with open("google_maps_export.csv", "w", newline="", encoding="utf-8") as f:
    writer = csv.DictWriter(f, fieldnames=fields, extrasaction="ignore")
    writer.writeheader()
    writer.writerows(all_results)
print(f"Exported {len(all_results)} businesses to google_maps_export.csv")

Step 4: Deduplicate by phone or address

Google Maps results across overlapping queries may include duplicates. Remove them by keying on phone number before writing the final CSV.

Python
seen = set()
unique = []
for biz in all_results:
    key = biz.get("phone") or biz.get("address", "")
    if key and key not in seen:
        seen.add(key)
        unique.append(biz)
print(f"Deduplicated: {len(all_results)} -> {len(unique)} businesses")
all_results = unique

Python Example

Python
import os
import csv
import requests

API_KEY = os.environ.get("SCAVIO_API_KEY", "your_scavio_api_key")
ENDPOINT = "https://api.scavio.dev/api/v1/search"

def fetch_maps(query: str) -> list[dict]:
    r = requests.post(
        ENDPOINT,
        headers={"x-api-key": API_KEY},
        json={"query": query, "platform": "google_maps"}
    )
    r.raise_for_status()
    return r.json().get("local_results", [])

def batch_export(categories: list[str], cities: list[str], output: str) -> None:
    all_biz = []
    for cat in categories:
        for city in cities:
            results = fetch_maps(f"{cat} in {city}")
            for biz in results:
                biz["category"] = cat
                biz["city"] = city
            all_biz.extend(results)
            print(f"{cat} in {city}: {len(results)} results")
    seen, unique = set(), []
    for biz in all_biz:
        key = biz.get("phone") or biz.get("address", "")
        if key and key not in seen:
            seen.add(key)
            unique.append(biz)
    fields = ["category", "city", "title", "address", "phone", "website", "rating", "reviews"]
    with open(output, "w", newline="", encoding="utf-8") as f:
        writer = csv.DictWriter(f, fieldnames=fields, extrasaction="ignore")
        writer.writeheader()
        writer.writerows(unique)
    print(f"Exported {len(unique)} unique businesses to {output}")

if __name__ == "__main__":
    batch_export(
        ["plumber", "electrician", "hvac contractor"],
        ["Austin TX", "Denver CO", "Portland OR"],
        "google_maps_export.csv"
    )

JavaScript Example

JavaScript
const API_KEY = process.env.SCAVIO_API_KEY || "your_scavio_api_key";
const ENDPOINT = "https://api.scavio.dev/api/v1/search";
const fs = require("fs");

async function fetchMaps(query) {
  const res = await fetch(ENDPOINT, {
    method: "POST",
    headers: { "x-api-key": API_KEY, "Content-Type": "application/json" },
    body: JSON.stringify({ query, platform: "google_maps" })
  });
  const data = await res.json();
  return data.local_results || [];
}

async function batchExport(categories, cities, output) {
  const all = [];
  for (const cat of categories) {
    for (const city of cities) {
      const results = await fetchMaps(`${cat} in ${city}`);
      results.forEach(b => { b.category = cat; b.city = city; });
      all.push(...results);
      console.log(`${cat} in ${city}: ${results.length} results`);
    }
  }
  const seen = new Set();
  const unique = all.filter(b => {
    const key = b.phone || b.address || "";
    if (key && !seen.has(key)) { seen.add(key); return true; }
    return false;
  });
  const header = "category,city,title,address,phone,website,rating,reviews";
  const rows = unique.map(b =>
    [b.category, b.city, b.title, b.address, b.phone, b.website, b.rating, b.reviews]
      .map(v => `"${(v || "").toString().replace(/"/g, '""')}"`).join(",")
  );
  fs.writeFileSync(output, [header, ...rows].join("\n"));
  console.log(`Exported ${unique.length} unique businesses to ${output}`);
}

batchExport(
  ["plumber", "electrician", "hvac contractor"],
  ["Austin TX", "Denver CO", "Portland OR"],
  "google_maps_export.csv"
).catch(console.error);

Expected Output

JSON
{
  "local_results": [
    {
      "position": 1,
      "title": "Radiant Plumbing & Air Conditioning",
      "address": "9521 US-290 W, Austin, TX 78736",
      "phone": "(512) 555-0147",
      "website": "https://radiantplumbing.com",
      "rating": 4.9,
      "reviews": 3842,
      "hours": "Open 24 hours",
      "type": "Plumber"
    }
  ]
}

Related Tutorials

Frequently Asked Questions

Most developers complete this tutorial in 15 to 30 minutes. You will need a Scavio API key (free tier works) and a working Python or JavaScript environment.

Python 3.8 or higher installed. requests and csv modules (csv is in the standard library). A Scavio API key from scavio.dev. A list of target categories and cities. A Scavio API key gives you 250 free credits per month.

Yes. The free tier includes 250 credits per month, which is more than enough to complete this tutorial and prototype a working solution.

Scavio has a native LangChain package (langchain-scavio), an MCP server, and a plain REST API that works with any HTTP client. This tutorial uses the raw REST API, but you can adapt to your framework of choice.

Start Building

Export local business data across multiple categories and cities to CSV using the Scavio API. Automate lead list generation without manual Maps scraping.