# Local Citation / NAP Consistency Scanner (`isotonic/local-citation-nap-consistency-scanner`) Actor

Scans public website and local citation surfaces for NAP and domain consistency using safe shallow fetches and deterministic fixtures.

- **URL**: https://apify.com/isotonic/local-citation-nap-consistency-scanner.md
- **Developed by:** [Brian Keefe](https://apify.com/isotonic) (community)
- **Categories:** SEO tools, Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.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/platform/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

## Local Citation / NAP Consistency Scanner

Production-ready Apify Actor that audits public local citation surfaces for NAP consistency.

### What it does

- Accepts canonical `businessName`, `address`, `phone`, `website` or `domain`, plus optional `city`, `state`, `country`, and `maxSources`.
- Scans shallow public sources only: official website, contact/about pages found on the same domain, Google/Bing SERP URLs, Yelp, Yellow Pages, BBB, and Chamber of Commerce search surfaces when feasible.
- Normalizes phone, address, and domain values enough for MVP comparison.
- Emits one dataset row per citation/source plus one summary audit row.
- Flags exact matches, near mismatches, hard mismatches, missing profiles, duplicate-looking listings, and wrong domains with evidence snippets.
- Supports deterministic `fixtureMode` for smoke tests and offline runs.

### Safety and scope

- No login flows, private APIs, CAPTCHAs, bypass behavior, or authenticated surfaces.
- Live crawling stays shallow: homepage, up to two same-domain contact/about/location pages, and a limited set of public search/directory URLs.
- Some directory/search pages may block or localize aggressively. The actor records those as missing or partial observations instead of failing the whole run.

### Input

Top-level single business fields:

- `businessName`
- `address`
- `phone`
- `website` or `domain`
- `city` optional
- `state` optional
- `country` optional
- `maxSources` optional, default `8`
- `fixtureMode` optional

Batch input is also supported with `businessRows`.

Fixture input is supported via `rawFixture` on a row or `fixtureBusinesses`.

Example:

```json
{
  "fixtureMode": true,
  "businessName": "Northwind Dental",
  "address": "123 Main Street Suite 200, Austin, TX 78701",
  "phone": "+1 (512) 555-0100",
  "website": "https://northwinddental.example",
  "city": "Austin",
  "state": "TX",
  "country": "USA",
  "maxSources": 7,
  "rawFixture": {
    "sources": []
  }
}
````

### Output

Each citation row includes:

- `rowType: "citation"`
- `sourceName`, `sourceType`, `sourceUrl`
- `status`, `severity`, `flags`, `confidence`
- canonical NAP/domain
- observed NAP/domain
- comparison fields
- `evidenceSnippet`

Each business also gets one summary row with:

- `rowType: "summary"`
- aggregate match counts
- overall `status`, `severity`, `flags`, `confidence`

### Local usage

Install dependencies:

```bash
npm install
```

Run locally with Apify storage:

```bash
mkdir -p ./apify_storage/key_value_stores/default
cp examples/sample-input.json ./apify_storage/key_value_stores/default/INPUT.json
CRAWLEE_STORAGE_DIR=./apify_storage ACTOR_DEFAULT_KEY_VALUE_STORE_ID=default ACTOR_INPUT_KEY=INPUT npm start
```

Run the deterministic smoke tests:

```bash
npm test
```

### Files

- Actor metadata: `.actor/actor.json`
- Input schema: `.actor/input_schema.json`
- Examples: `examples/sample-input.json`, `examples/sample-output.json`
- Source code: `src/`
- Smoke tests: `tests/smoke/`

# Actor input Schema

## `businessName` (type: `string`):

Canonical business name to compare against public citations.

## `address` (type: `string`):

Canonical street address.

## `phone` (type: `string`):

Canonical phone number.

## `website` (type: `string`):

Official website URL or domain for domain matching.

## `city` (type: `string`):

Optional city used to build local citation search URLs and improve address comparison.

## `state` (type: `string`):

Optional state, province, or region used to build local citation search URLs.

## `country` (type: `string`):

Optional country used to build local citation search URLs.

## `maxSources` (type: `integer`):

Maximum number of live citation surfaces to scan per business.

## `fixtureMode` (type: `boolean`):

Skip live fetches and use only provided fixture data for deterministic runs and smoke tests.

## `businessRows` (type: `array`):

Optional batch input. Each row may contain businessName, address, phone, website/domain, city/state/country, maxSources, and rawFixture.

## `fixtureBusinesses` (type: `array`):

Deterministic fixture businesses with raw citation source observations used for offline tests.

## Actor input object example

```json
{
  "country": "USA",
  "maxSources": 8,
  "fixtureMode": false
}
```

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("isotonic/local-citation-nap-consistency-scanner").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("isotonic/local-citation-nap-consistency-scanner").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 '{}' |
apify call isotonic/local-citation-nap-consistency-scanner --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=isotonic/local-citation-nap-consistency-scanner",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Local Citation / NAP Consistency Scanner",
        "description": "Scans public website and local citation surfaces for NAP and domain consistency using safe shallow fetches and deterministic fixtures.",
        "version": "0.1",
        "x-build-id": "QSgL0ALEakHJxydZT"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/isotonic~local-citation-nap-consistency-scanner/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-isotonic-local-citation-nap-consistency-scanner",
                "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/isotonic~local-citation-nap-consistency-scanner/runs": {
            "post": {
                "operationId": "runs-sync-isotonic-local-citation-nap-consistency-scanner",
                "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/isotonic~local-citation-nap-consistency-scanner/run-sync": {
            "post": {
                "operationId": "run-sync-isotonic-local-citation-nap-consistency-scanner",
                "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",
                "properties": {
                    "businessName": {
                        "title": "Business name",
                        "type": "string",
                        "description": "Canonical business name to compare against public citations."
                    },
                    "address": {
                        "title": "Address",
                        "type": "string",
                        "description": "Canonical street address."
                    },
                    "phone": {
                        "title": "Phone",
                        "type": "string",
                        "description": "Canonical phone number."
                    },
                    "website": {
                        "title": "Website or domain",
                        "type": "string",
                        "description": "Official website URL or domain for domain matching."
                    },
                    "city": {
                        "title": "City",
                        "type": "string",
                        "description": "Optional city used to build local citation search URLs and improve address comparison."
                    },
                    "state": {
                        "title": "State or region",
                        "type": "string",
                        "description": "Optional state, province, or region used to build local citation search URLs."
                    },
                    "country": {
                        "title": "Country",
                        "type": "string",
                        "description": "Optional country used to build local citation search URLs.",
                        "default": "USA"
                    },
                    "maxSources": {
                        "title": "Max sources",
                        "minimum": 1,
                        "maximum": 12,
                        "type": "integer",
                        "description": "Maximum number of live citation surfaces to scan per business.",
                        "default": 8
                    },
                    "fixtureMode": {
                        "title": "Fixture mode",
                        "type": "boolean",
                        "description": "Skip live fetches and use only provided fixture data for deterministic runs and smoke tests.",
                        "default": false
                    },
                    "businessRows": {
                        "title": "Business rows",
                        "type": "array",
                        "description": "Optional batch input. Each row may contain businessName, address, phone, website/domain, city/state/country, maxSources, and rawFixture."
                    },
                    "fixtureBusinesses": {
                        "title": "Fixture businesses",
                        "type": "array",
                        "description": "Deterministic fixture businesses with raw citation source observations used for offline tests."
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
