# Local Keyword Search Volume by City - Local Market Sizer (`wrenfield-data/local-keyword-demand`) Actor

Size a local service market city by city: real Google Keyword Planner search volume, CPC and top-of-page bids for 'plumber near me', '{service} {city}' and more, for up to 50 cities per run. Cities ranked, report included.

- **URL**: https://apify.com/wrenfield-data/local-keyword-demand.md
- **Developed by:** [Wrenfield Data](https://apify.com/wrenfield-data) (community)
- **Categories:** SEO tools, Lead generation, AI
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 keyword with searches in a cities

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Local Keyword Search Volume by City — Local Market Sizer

**Find out how many people in each city search for a service, what advertisers pay per click there, and which city is the best market. Real Google Ads Keyword Planner numbers for up to 50 cities per run, with no Google Ads account and no ad spend.**

Google's Keyword Planner shows only ranges ("100–1K") unless your account is spending on ads, and city-level checks are one city at a time. This Actor gives exact Keyword Planner averages city by city. It builds the local keyword set for you ("plumber near me", "plumber austin", "emergency plumber", "plumber cost"...) and ranks the cities.

### Who uses it

- **Local SEO and PPC agencies**: size a prospect's market before the sales call ("1,900 people a month search for your service in your city, and advertisers pay up to $45 a click"), choose which suburbs get service-area pages, and price the retainer.
- **Lead-gen and rank-and-rent builders**: compare 20–50 cities for one service and pick the ones with demand and high CPCs.
- **Franchises and multi-location businesses**: rank expansion cities by real search demand.
- **Home-service, dental, legal and medical marketers**, anywhere Google Ads runs (US, UK, Canada, Australia, South Africa, Latin America, Europe, India...).

### What you get

- **One row per city × keyword:** monthly searches from that city, CPC, top-of-page bid range, competition, high-intent flag, peak and low month, 12-month history.
- **Cities ranked** (`CITIES`, `CITIES.csv`, `REPORT.html`): total monthly searches per service, high-intent share, average CPC, highest top-of-page bid, search value index and top keyword.
- **Honest totals:** Google reports close variants ("plumber near me" / "plumbers near me") as one group with the same numbers. We mark those rows (`grouped_with`) and count each group once in city totals.

### Example (real run, Nov 3, 2026)

Input: services `pool cleaning`, `pool repair`; cities `Virginia Beach, Virginia`, `Chesapeake, Virginia`.

| # | city | service | monthly searches | high-intent share | avg CPC | top keyword |
|---|---|---|---|---|---|---|
| 1 | Virginia Beach, VA | pool cleaning | 170 | 52.9% | $22.93 | pool cleaning services |
| 2 | Virginia Beach, VA | pool repair | 110 | 100% | $15.24 | pool repair near me |
| 3 | Chesapeake, VA | pool cleaning | 100 | 60% | $9.61 | pool cleaning services |
| 4 | Chesapeake, VA | pool repair | 60 | 100% | $0.37 | pool repair |

Sample rows:

| city | keyword | monthly searches | CPC | top-of-page bid (high) | competition |
|---|---|---|---|---|---|
| Virginia Beach | pool cleaning services | 50 | $22.37 | $15.00 | LOW |
| Virginia Beach | pool cleaning | 40 | $33.63 | $15.00 | HIGH |
| Virginia Beach | pool repair near me | 30 | $17.18 | — | LOW |
| Virginia Beach | pool repair virginia beach | 20 | $24.55 | $20.22 | HIGH |

What the run shows: Virginia Beach has about 1.7x Chesapeake's pool-cleaning demand, and its clicks cost more than twice as much.

### Input

```json
{
  "services": ["plumber", "water heater repair"],
  "cities": ["Austin, Texas", "Round Rock, Texas", "San Antonio, Texas"],
  "keywordTemplates": [],
  "extraKeywords": []
}
```

- `services`: what the business sells, as people search it.
- `cities`: city, county, metro (DMA) or region names, e.g. "Austin, Texas", "Round Rock, TX", "Leeds, England", "Bogota, Colombia". Up to 50.
- `keywordTemplates` (optional): patterns with `{service}` and `{city}`. Default: 14 English patterns. For other languages, add your own, e.g. `{service} cerca de mi`, `{service} en {city}`, `{service} perto de mim`.
- `extraKeywords` (optional): competitor brands or anything else, checked in every city.

### Pricing (pay per event)

- **$0.20 per city** (one live Keyword Planner lookup of up to 1,000 keywords).
- **$0.004 per keyword row with searches.** Keywords with no measurable searches are free.
- Example: 2 services × 14 templates in 10 cities is at most 10 × $0.20 + 280 × $0.004 = **$3.12**.
- **Free Apify plan:** 1 city and 15 keywords per day.
- Set "Maximum cost per run" and the Actor stops before exceeding it.

### Data and limits

- Numbers come from Google Ads Keyword Planner, fetched live: monthly averages of the last 12 months for searches made from that location. Google rounds small volumes (10, 20, 30...) and leaves many long-tail local phrases blank. Blank rows are free.
- CPC and bids are what advertisers paid, in USD.
- `monthly_search_value_usd` = searches × CPC. It is an upper-bound index for comparing cities, not a revenue forecast.
- Countries Google Ads does not serve (e.g. Russia, Iran) are not available.

### Related Wrenfield Data Actors

- **Keyword Search Volume** (wrenfield-data/keyword-search-volume): any keyword list, one location, plus keyword ideas.
- **Keyword Search Volume by Country** (wrenfield-data/keyword-demand-by-country): one keyword list across up to 94 countries.
- **Google Maps Grid Rank Tracker** (wrenfield-data/google-maps-grid-rank-tracker): where a business ranks on the map across a city.

# Actor input Schema

## `services` (type: `array`):

What the business sells, as people search it: 'plumber', 'water heater repair', 'dentist', 'dental implants', 'roofing'. Each one is expanded with the keyword templates below.

## `cities` (type: `array`):

Cities, counties, metro (DMA) areas or regions, e.g. 'Austin, Texas', 'Round Rock, TX', 'Pretoria, South Africa', 'Bogota, Colombia'. Up to 50 per run.

## `keywordTemplates` (type: `array`):

Patterns with {service} and optionally {city}. Leave empty for the default 14: {service}, {service} near me, {service} {city}, {service} in {city}, best {service}, best {service} {city}, {service} cost, {service} prices, emergency {service}, 24 hour {service}, affordable {service}, {service} company, {service} services, local {service}. Use local-language templates for other countries (e.g. '{service} cerca de mi', '{service} en {city}').

## `extraKeywords` (type: `array`):

Any other keywords to check in every city, e.g. competitor brand names. {city} is replaced with the city name.

## `language` (type: `string`):

Leave empty for all languages (recommended for local searches).

## `includeEmptyRows` (type: `boolean`):

Also list keywords with no measurable searches in a city (never charged).

## Actor input object example

```json
{
  "services": [
    "plumber",
    "water heater repair"
  ],
  "cities": [
    "Austin, Texas",
    "Round Rock, Texas",
    "San Antonio, Texas"
  ],
  "includeEmptyRows": true
}
```

# Actor output Schema

## `rows` (type: `string`):

No description

## `report` (type: `string`):

No description

## `cities` (type: `string`):

No description

## `citiesCsv` (type: `string`):

No description

## `allFields` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "services": [
        "plumber",
        "water heater repair"
    ],
    "cities": [
        "Austin, Texas",
        "Round Rock, Texas",
        "San Antonio, Texas"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("wrenfield-data/local-keyword-demand").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "services": [
        "plumber",
        "water heater repair",
    ],
    "cities": [
        "Austin, Texas",
        "Round Rock, Texas",
        "San Antonio, Texas",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("wrenfield-data/local-keyword-demand").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "services": [
    "plumber",
    "water heater repair"
  ],
  "cities": [
    "Austin, Texas",
    "Round Rock, Texas",
    "San Antonio, Texas"
  ]
}' |
apify call wrenfield-data/local-keyword-demand --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,wrenfield-data/local-keyword-demand"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/0vbkHtcBpaz01tj2E/builds/73j46hb9RSzFtyB41/openapi.json
