# Retail Chain Locations & Openings Tracker (`monteva/retail-chain-locations-tracker`) Actor

Get every store location for any retail, restaurant or service chain — straight from its own public store locator. Run on a schedule to track store openings & closings. Pay-per-result, no enterprise contract.

- **URL**: https://apify.com/monteva/retail-chain-locations-tracker.md
- **Developed by:** [monteva](https://apify.com/monteva) (community)
- **Categories:** Real estate, E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 store location scrapeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js/docs.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/integrations/mcp.md).

If your project is in a different language, use the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).


# README

## Retail Chain Locations & Openings Tracker

Get the **complete, structured list of store locations for any retail, restaurant or service chain** — straight from the chain's own public store locator. Run it on a schedule and the Actor also **tracks store openings and closings** for you: every location is tagged `added`, `removed` or `unchanged` compared to your previous run.

Commercial location datasets of this kind (ChainXY, AggData, Coresight store trackers) cost hundreds to thousands of dollars per year. This Actor gives you the same core data — locations plus openings/closings history — at pay-per-result prices, for exactly the chains you care about.

### What you get per location

| Field | Example |
|---|---|
| `brand` / `brandHost` | Example Chain / examplechain.com |
| `name` | Example Chain Downtown Zurich |
| `address1`, `address2`, `city`, `region`, `postalCode`, `country` | Bahnhofstrasse 1, Zurich, ZH, 8001, CH |
| `latitude`, `longitude` | 47.3769, 8.5417 |
| `phone`, `website`, `hours` | +41 …, https://…, Mon–Sat 9–20 |
| `changeStatus` | `initial` \| `added` \| `removed` \| `unchanged` |
| `source`, `sourceUrl` | storemapper / json-ld / sitemap-json-ld … |
| `locationKey`, `scrapedAt` | stable ID for diffing, ISO timestamp |

### How it works

1. **Paste chain websites or locator URLs** — one or many. The Actor finds the store-locator page automatically if you give it just the homepage.
2. **Auto-detection of the locator backend.** Many chains run their locator on a hosted platform with an open JSON endpoint — Storemapper, Stockist, Uberall or Locally. One adapter per platform covers hundreds of chains with perfectly structured data.
3. **Robust fallbacks.** No platform detected? The Actor parses location data embedded in the locator page (JSON blobs, schema.org data — including data delivered in plain or typeless `<script>` tags, not just canonical JSON-LD) or crawls the chain's sitemap for individual location pages (the pattern used by Yext-style directory sites).
4. **Openings & closings tracking.** Each run stores a compact snapshot per chain. On the next run, new locations come back as `added`, disappeared ones as `removed` — including their last known address. Schedule the Actor weekly or monthly per chain and you have a store openings/closings feed.

### Supported store locators (please read before your first run)

This Actor reads location data that a chain exposes on its **public, server-rendered** pages. It works well when a chain's locator uses any of:

- one of the supported platforms (Storemapper, Stockist, Uberall, Locally),
- embedded JSON or schema.org data in the locator/location pages, or
- a sitemap of individual, server-rendered location pages.

It will **not** extract from fully dynamic, JavaScript-only locators that load their data from a private API with no public endpoint, or from pages behind aggressive anti-bot protection. For those a chain returns zero results and logs a clear note. If that happens for a chain you need, open an issue with the URL — adding an adapter is usually quick and benefits everyone. **Tip:** most store locators sit behind a CDN, so the Actor uses Apify Proxy by default; for a heavily protected chain, switch the proxy group to `RESIDENTIAL` in the input.

### Who uses this data

- **Commercial real estate & site selection** — competitor and tenant footprints, kept current.
- **CPG & supplier sales teams** — a chain opening stores = new accounts and territory planning.
- **Market intelligence / alternative data** — store counts as growth signal per chain and region.
- **Franchise & expansion consultants, AI agent builders** — clean POI feeds without enterprise contracts.

### Pricing & cost control

You pay per delivered location record (pay-per-event) — platform usage is included, so there are no separate compute or proxy charges. Use `maxLocationsPerBrand` for a cheap test run first — while a test limit is active no snapshot is saved, so your change tracking stays accurate. In monitoring mode (`pushUnchanged: false`), repeat runs only bill the changes, which makes weekly schedules very cheap. You can also cap the maximum charge per run in the run options.

### FAQ

**Is this legal?** The Actor only reads public store-locator pages that chains publish precisely so that their locations can be found — no logins, no personal data, only business location facts. It respects `robots.txt` when discovering sitemaps. As with any scraping, review the target site's terms and use the data responsibly.

**A chain returns no results — what now?** Some chains use fully dynamic, JS-only locators without a public data endpoint, or block automated traffic. Open an issue with the chain's URL — adding an adapter is usually quick.

**Can I export to Excel/Sheets?** Yes — like any Apify dataset: CSV, Excel, JSON, API, or integrations (Google Sheets, Zapier, Make).

**How do I build a full openings/closings history?** Create a Schedule for this Actor with your chain list. Each run's dataset contains the diff; the **Openings & closings** dataset view filters to `added`/`removed` only.

---

**Maintained by monteva.** Reliable data & automation tools for businesses and AI agents — documented, monitored, maintained. Machine-readable by design (MCP-ready). Issues answered within 24h.
Contact: hello@monteva.io · [monteva.io](https://monteva.io) · more tools at [apify.com/monteva](https://apify.com/monteva)

# Actor input Schema

## `targets` (type: `array`):

One or more retail/restaurant/service chain websites (e.g. `examplechain.com`) or direct store-locator URLs (e.g. `https://www.examplechain.com/store-locator`). The Actor auto-detects the locator backend (Storemapper, Stockist, Uberall, Locally, embedded JSON, JSON-LD, sitemap location pages).
## `changeTracking` (type: `boolean`):

Compare each run against the previous snapshot of the same chain and tag every location as `initial`, `added`, `removed` or `unchanged`. Run this Actor on a schedule (e.g. weekly) to get a continuous openings/closings feed per chain.
## `pushUnchanged` (type: `boolean`):

If disabled, repeat runs only output `added` and `removed` locations (pure monitoring mode — fewer results, lower cost). The first run always outputs the full list.
## `maxLocationsPerBrand` (type: `integer`):

Limit the number of locations extracted per chain (0 = no limit). Prefilled with a small value for a cheap first test run. Set to 0 for the full list and to enable change tracking. While a test limit is active, no snapshot is saved, so change tracking stays accurate.
## `maxDetailPages` (type: `integer`):

Upper bound for individual location pages fetched in the sitemap fallback (used for chains without an open locator API, e.g. Yext-powered sites). Set 0 to disable the sitemap fallback.
## `stateStoreName` (type: `string`):

Name of the key-value store that holds per-chain snapshots for change tracking. Use different names to keep separate tracking universes (e.g. per client).
## `proxyConfiguration` (type: `object`):

Proxy used for fetching. On by default (Apify Proxy) — most store locators sit behind CDNs/bot-protection that reject bare datacenter IPs. For heavily protected chains, switch to the RESIDENTIAL group here. To disable, set useApifyProxy to false.

## Actor input object example

```json
{
  "targets": [
    "https://locations.dennys.com"
  ],
  "changeTracking": true,
  "pushUnchanged": true,
  "maxLocationsPerBrand": 25,
  "maxDetailPages": 300,
  "stateStoreName": "retail-chain-locations-state",
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
````

# 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 = {
    "targets": [
        "https://locations.dennys.com"
    ],
    "maxLocationsPerBrand": 25,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("monteva/retail-chain-locations-tracker").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 = {
    "targets": ["https://locations.dennys.com"],
    "maxLocationsPerBrand": 25,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("monteva/retail-chain-locations-tracker").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "targets": [
    "https://locations.dennys.com"
  ],
  "maxLocationsPerBrand": 25,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call monteva/retail-chain-locations-tracker --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=monteva/retail-chain-locations-tracker",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Retail Chain Locations & Openings Tracker",
        "description": "Get every store location for any retail, restaurant or service chain — straight from its own public store locator. Run on a schedule to track store openings & closings. Pay-per-result, no enterprise contract.",
        "version": "0.0",
        "x-build-id": "Xg1PDKjztNFDnyfNn"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/monteva~retail-chain-locations-tracker/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-monteva-retail-chain-locations-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/monteva~retail-chain-locations-tracker/runs": {
            "post": {
                "operationId": "runs-sync-monteva-retail-chain-locations-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/monteva~retail-chain-locations-tracker/run-sync": {
            "post": {
                "operationId": "run-sync-monteva-retail-chain-locations-tracker",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "targets"
                ],
                "properties": {
                    "targets": {
                        "title": "Chain websites or store-locator URLs",
                        "type": "array",
                        "description": "One or more retail/restaurant/service chain websites (e.g. `examplechain.com`) or direct store-locator URLs (e.g. `https://www.examplechain.com/store-locator`). The Actor auto-detects the locator backend (Storemapper, Stockist, Uberall, Locally, embedded JSON, JSON-LD, sitemap location pages).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "changeTracking": {
                        "title": "Track openings & closings",
                        "type": "boolean",
                        "description": "Compare each run against the previous snapshot of the same chain and tag every location as `initial`, `added`, `removed` or `unchanged`. Run this Actor on a schedule (e.g. weekly) to get a continuous openings/closings feed per chain.",
                        "default": true
                    },
                    "pushUnchanged": {
                        "title": "Include unchanged locations in output",
                        "type": "boolean",
                        "description": "If disabled, repeat runs only output `added` and `removed` locations (pure monitoring mode — fewer results, lower cost). The first run always outputs the full list.",
                        "default": true
                    },
                    "maxLocationsPerBrand": {
                        "title": "Max locations per chain (test limit)",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Limit the number of locations extracted per chain (0 = no limit). Prefilled with a small value for a cheap first test run. Set to 0 for the full list and to enable change tracking. While a test limit is active, no snapshot is saved, so change tracking stays accurate.",
                        "default": 0
                    },
                    "maxDetailPages": {
                        "title": "Max sitemap pages per chain",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Upper bound for individual location pages fetched in the sitemap fallback (used for chains without an open locator API, e.g. Yext-powered sites). Set 0 to disable the sitemap fallback.",
                        "default": 300
                    },
                    "stateStoreName": {
                        "title": "State store name",
                        "type": "string",
                        "description": "Name of the key-value store that holds per-chain snapshots for change tracking. Use different names to keep separate tracking universes (e.g. per client).",
                        "default": "retail-chain-locations-state"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxy used for fetching. On by default (Apify Proxy) — most store locators sit behind CDNs/bot-protection that reject bare datacenter IPs. For heavily protected chains, switch to the RESIDENTIAL group here. To disable, set useApifyProxy to false.",
                        "default": {
                            "useApifyProxy": true
                        }
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
