Citation God Mode - NAP Consistency Checker
Pricing
from $0.01 / 1,000 results
Citation God Mode - NAP Consistency Checker
Checks a local business's name, address and phone against 58 directories (up to 32 per scan, by industry) plus Moz Local, and reports matching, wrong and missing listings as JSON. For every directory, allow a max cost per run of $3 (quick, standard), $4 (deep) or $5 (god-mode).
Pricing
from $0.01 / 1,000 results
Rating
0.0
(0)
Developer
The Howlers
Maintained by CommunityActor stats
3
Bookmarked
27
Total users
1
Monthly active users
4 hours ago
Last modified
Categories
Security
Limited permissionsShare
Checks a local business's name, address and phone (NAP) across online directories and reports which listings match, which are wrong, and which are missing. It works from a list of 63 directories and checks up to 46 of them in one scan for a business in one industry: 41 general directories for every business, plus the ones for its industry. On top of that it runs a Moz Local listing scan, which covers about a dozen major directories.
Most directories are checked directly: our dedicated scrapers, each directory's own public search read inside this Actor, or the directory's own phone lookup. Google's results are used for three directories that have no direct check, and as a fallback when a direct check cannot read a site. A cross-validation step works out the most likely correct NAP from every source, and an optional Claude analysis writes fix suggestions.
Each run returns one structured JSON item: a row per directory with the same fields every time (status, listing URL, the name, address and phone found, whether each matches, where the evidence came from, and the issues), plus the cross-validated NAP and a score. Load it into your own app through the Apify API, or have it posted to your webhookUrl when the run ends.
Bring your own keys: an Anthropic key for the AI analysis and a Firecrawl key for Firecrawl extraction are optional. Without them the scan still runs; those parts are skipped.
Set your maximum cost per run
Set the maximum cost per run high enough for the scan mode you choose, or some directories come back as not_checked. Each directory with a dedicated scraper is checked by its own sub-run, an Actor run on your Apify account billed at that scraper's prices. While a sub-run runs, it holds its share of this run's maximum cost per run (usually $1, the minimum each scraper requires), so the scan can keep the sub-runs inside your maximum. When the shares do not all fit at once, the sub-runs take turns: each waits for the ones before it to finish, and only what a finished sub-run actually charged stays counted. A directory is not checked only when its sub-run still does not fit when its turn comes. You are charged only for what the scan uses, so a higher maximum does not raise the bill; it only lets more sub-runs run at once.
| Scan mode | Lowest maximum that usually checks every directory (sub-runs take turns) | Maximum that runs every scraper at once (fastest) | A complete scan usually charges, sub-runs included |
|---|---|---|---|
quick | $3 (the Actor's minimum) | $3.50 | about $1.45 |
standard | $3 (the Actor's minimum) | $5.50 | about $2.15 |
deep | $3.50; $4 for contractors and home services | $6.50 to $7.50; $9.50 for contractors and home services | about $2.45 to $3.05 |
god-mode | $3.50; $4 for contractors and home services; $5 for restaurants, software companies and agencies | $6.50 to $7.50; $9.50 for contractors, home services and restaurants; $11.50 for software companies and agencies | about $2.45 to $3.80 |
These amounts are for the default 4 GB of memory and the scrapers' prices on 2026-11-09. Each run works out its own amounts at the start, from the directories it will check and the scrapers' current prices. When your maximum is below what the sub-runs need even taking turns, the run's status says so from the start: "may" when some directories may be skipped ("Your maximum cost per run is $2.50. A complete standard scan usually needs about $3.00 even with our scrapers taking turns, so some directories may be returned as not_checked. Set it to at least $3.00 to check every directory, or about $5.50 to run all of our scrapers at once."), and "will" when at least one cannot fit whatever the sub-runs charge. A maximum between the two amounts gets no warning: the scan usually checks everything, only more slowly. The final status gives the scan's counts and how many directories were skipped. In the output, budgetLimited, directoriesSkippedForBudget, minimumMaxTotalChargeUsd and recommendedMaxTotalChargeUsd say what was skipped and what maximum to set, and each skipped row's relevanceReason says it was skipped for the run's maximum cost. A run started through the API without a maximum uses your account's limit and checks every directory.
Quick Start
{"businessName": "Acme Heating & Air","streetAddress": "123 Main St","city": "Wichita","state": "KS","zipCode": "67202","phone": "(316) 555-0100","website": "https://acmeheating.example","industry": "HVAC contractor","scanMode": "standard","providedUrls": { "Yelp": "https://www.yelp.com/biz/acme-heating-and-air-wichita" }}
Run without a business name, city and state (or with demoMode: true) to get a labeled sample report. Sample runs charge no scan event.
Which directories are checked
The list has 63 directories. One of them, Google Business Profile, is the source of truth when you give a Place ID or its URL; the scan does not check it. Of the other 62:
- 41 general directories are checked for every business. Justdial lists businesses in India only, so for a US business it is
n/aand 40 are checked. - 18 list only one kind of business, and are checked only for that kind (
n/aotherwise). - 3 are not checked and are always reported as
not_checked: eLocal, Kompass and YellowBot (the reason for each is inrelevanceReason).
The scan mode picks which directories are in the scan, and the business's industry decides which industry directories stay in:
| Scan mode | Directories in the mode | Checked for a business in one industry |
|---|---|---|
quick | 7 | 7 |
standard | 14 | 13, or 14 for a restaurant, hotel or attraction |
deep | 51 | 41, plus up to 3 for its industry (up to 44) |
god-mode | 62 | 41, plus up to 5 for its industry (up to 46) |
A business that fits two industries, such as a hotel with a restaurant, gets the directories of both. A directory that needs a key you did not give, or a check that cannot tell this business's listing from another location's, is reported as not_checked, so a scan can check fewer than these numbers.
How the directories are checked:
- Our dedicated scrapers (21): Yelp, Bing Places, Apple Maps, Yellow Pages, BBB, Manta, Trustpilot, Angi, HomeAdvisor, Houzz, Healthgrades, Avvo, DoorDash, Grubhub, Uber Eats, Glassdoor, G2, Capterra, Clutch, GoodFirms and Crunchbase. Each runs as its own Actor and reads the directory's public pages. Yellow Pages is searched by name and by phone number in the same run (no second Actor start; the Yellow Pages scraper adds its $0.005 listing charge only for a listing that shows this phone and that the name search did not already return). The phone results are used only when no listing found by name is this business's: Yellow Pages files some names with broken letters ("EÅ?S Fitness" for EōS Fitness) that no name search finds, and a listing found by phone counts only when it also shows this street and city. A listing that shows this street and this phone under a shortened or extended form of the name ("Katz's Deli" for Katz's Delicatessen, "Katz's Famous Delicatessen") is this business's listing, never missing:
correctwhen the name is an accepted short form ("Deli" for "Delicatessen", "St." for "Saint", "Bros" for "Brothers"),incorrectwith a name mismatch otherwise. Another name at the same street and phone ("Eat", in the same building) is not counted, and neither is a short name at this street with another phone. Healthgrades is searched by the practice name and, in the same run, by the practitioners' names, because Healthgrades often lists a practice only under each practitioner's own profile ("Dr. Jane Hollis, DDS" for Hollis Dental Co., "Dr. John Roe, DMD" for Lakeside Smile Dental). The names are the ones given inproviderNamesor, when it is empty, the names the practice's own website shows (names shown with "Dr." first, then names shown with a credential such as DDS or DMD, two at most), plus the surname of a practice named for a person ("Hollis"). Such a profile counts only when it shows this phone number or street, and is reported asfoundbecause its name is the practitioner's; when its address or phone does not match, it isincorrectand its issues still say it is the practitioner's own profile. MD and DC are also state codes, so these rules tell a town from a person. A " - The directory's own public search, read inside this Actor (15): Merchant Circle, Chamberofcommerce.com, CitySquares, ShowMeLocal, Data Axle, Neustar Localeze, Brownbook, Tupalo, Birdeye, ZipLeaf, GoLocal247, YellowPageCity, Hub.biz, DexKnows and TikTok. Data Axle and Localeze are searched by phone number and by name, and DexKnows by name and then by phone number. TikTok profiles cannot be searched by name without a signed-in account, so the scan checks the TikTok account the business's website links to (or a saved TikTok URL), and reports
not_checkedwhen there is neither. - The directory's own phone lookup (2): iBegin and 2FindLocal. A listing that carries a different or old phone number is not found, so a "missing" there means no listing uses the phone number checked.
- Google's results (3): MapQuest, TripAdvisor and Thumbtack, whose pages do not answer automated checks. A listing Google shows is reported with its URL; Google's results do not show phone numbers, so phones are not compared there. Thumbtack is indexed only in part, so no hit there is
not_checked, nevermissing. - A browser check (18): Facebook, Foursquare, SuperPages, Hotfrog, LinkedIn, Instagram, Citysearch, Ezlocal, Zillow, OpenTable, Indeed, Nextdoor, Alignable, Cylex, n49, Justdial, YouTube and Twitter: the directory's own search where it has one, else Google's results for the directory. "Missing" needs the directory's own search to answer; no Google hit is
not_checked, and a search that did not answer iserror.
Pages are read with real-browser fingerprints (Camoufox, or a Chrome TLS fingerprint for plain pages) through residential US connections, at a human pace. A site's automatic bot check is waited out, never clicked or solved; a site that still blocks the check is error (not verified), never missing. Only public pages are read, with no logins.
Names are compared as whole words ("Ollis Dental" is not "Hollis Dental Co."); with no matching phone or street, the first word must match exactly ("Star Roofing" is not "Stars Roofing", "A&E" is not "A&B"), though a name written without spaces ("Bluesky") or with an apostrophe ("Joe's") still matches; and a listing elsewhere is called another location of the brand only when it shows this business's phone number or website, or is named for another place; a listing that only shares the name is reported as a same-name listing. Which listing is this business's is decided by one rule for every directory: a listing counts when it shows this street or this phone number, or when it is the only listing with this name in this city. When several listings could be this one and nothing tells them apart (another location of the same brand, a division at another address), the row is not_checked and names them; other listings of the brand are named in issues, and a listing with this name at this street or phone is reported there as a duplicate.
A listing is correct only when its name, address and phone number were all compared with the business's and all match. When one of them could not be compared (the directory does not show it, Google's copy of the listing does not show it, or the listing is a saved URL that was not read), the listing is found, and issues says what was not compared. An address that shows only the city and ZIP does not count as the street compared.
Some brands use one phone number at every office. When listings for the business's name show its phone number at several other addresses, the number no longer tells the offices apart: a listing tied to the business only by that number at another address is not_checked (it may be another office's), and listings of other offices are not called duplicates. A listing at the office's old address still counts when the scan can tell which address that was (a listing the scan matched at the current address still carries the old street in its URL).
A listing whose name is close to the business's but not the same ("Smiths Plumbing" for Smith Plumbing, "Pro Roofing" for Professional Roofing, "The Dental Center" for Dental Center of Tulsa) and that shows neither this street nor this phone number is reported as possible_match: the row names the listing (foundName, foundAddress, foundPhone, url), and relevanceReason says what does not tie it. A possible match counts as neither listed nor missing and is left out of the score (summary.possibleMatches counts them), so a person can confirm or reject it. A close name at another street with another phone number, or in another city, is another business and the directory stays missing.
Two kinds of directory are skipped instead of checked, and neither is ever reported as missing or counted in the score:
n/a(not applicable): directories that only list one kind of business are checked only for that kind of business. DoorDash, Grubhub, Uber Eats and OpenTable are checked for restaurants and food businesses, TripAdvisor for restaurants, hotels and attractions, Avvo for lawyers, Healthgrades for healthcare providers, Angi and HomeAdvisor for home service and construction businesses, Houzz for those and for real estate, Zillow for real estate, G2, Capterra, Clutch, GoodFirms and Crunchbase for software and agencies, and Glassdoor and Indeed for large employers and staffing firms. Every other directory is checked for every business.not_checked: directories this scan cannot verify. eLocal lists only its paid advertisers in its public search, Kompass blocks automated visits, and YellowBot's site is down. A check that cannot tell this business from another location of the same brand is alsonot_checked, as are Avvo and Glassdoor when nofirecrawlApiKeyis given.
Skipped directories start no sub-run, so they cost nothing. If a saved URL or the Moz scan shows a listing on a skipped directory, that listing is still reported. A Moz Local "no listing" is never reported as missing on its own (it has been wrong for listed businesses): a directory only Moz Local looked at, with no listing there, is not_checked.
Infogroup is Data Axle's former name, so it is reported as Data Axle. Factual merged into Foursquare in 2020 and is no longer reported. Acxiom (closed its directory in 2019), LocalStack (site down), Local.com (now a product-review site) and Spoke (directory pages removed) left the list in build 1.5.3; Birdeye, ZipLeaf, GoLocal247, YellowPageCity and Hub.biz joined it in build 1.5.13.
How the industry is decided: from the industry input when it names a trade (a Google Business Profile category such as "HVAC contractor" or "Italian restaurant", or a word such as "plumber", "lawyer", "dentist"). When industry is empty or general, the business name is read ("Smith Law Office", "Bright Smile Dental"). When neither says, the industry is unknown: general directories are checked as usual and the industry-specific ones are skipped as n/a. The detected industry is in the output as detectedIndustry. Naming a directory in platforms, or saving its URL in providedUrls, checks it whatever the industry.
Input Parameters
| Parameter | Type | Default | Required | Description |
|---|---|---|---|---|
businessName | string | - | Yes | The exact business name to check |
streetAddress | string | - | No | Street address (e.g., '123 Main St Suite 100'). The Moz scan needs it. |
city | string | - | Yes | City name |
state | string | - | Yes | State abbreviation (e.g., 'FL', 'CA') |
zipCode | string | - | No | 5-digit ZIP code |
phone | string | - | No | Business phone number in any format. Without it, phone numbers are not compared. |
website | string | - | No | Business website |
industry | string | - | No | The business's industry or Google Business Profile category (e.g., 'restaurant', 'HVAC contractor', 'law firm', 'dentist'). Decides which industry-specific directories are checked. See "Which directories are checked". |
providerNames | array | - | No | The names of the doctors, dentists or other practitioners at this location (e.g., 'Dr. John Roe'), up to 3. Healthgrades is also searched by these names, and such a profile counts only when it shows this phone number or street. When empty, a healthcare practice's website is read for the names. |
googlePlaceId | string | - | No | Google Maps Place ID. When given, the Google Business Profile is the source of truth and marked correct. |
scanMode | string | "standard" | No | quick (the 7 critical directories), standard (the 14 most important), deep (51: every directory except food delivery, employer and software review sites), god-mode (all 62). See "Which directories are checked". |
enableMozScan | boolean | true | No | Run the Moz Local listing check (free; its report covers about a dozen major directories) |
enableDirectScrape | boolean | true | No | Check directories directly for detailed NAP data |
useDedicatedScrapers | boolean | true | No | Use our dedicated Apify scrapers for the directories that have one (Yelp, BBB, Yellow Pages, Apple Maps, Bing Places, Manta, Trustpilot, Angi, Houzz, Clutch and others). They run as separate Actors on your account. |
enableFirecrawl | boolean | true | No | Use Firecrawl for directories without a dedicated scraper (needs firecrawlApiKey) |
firecrawlApiKey | string | - | No | Your Firecrawl API key. Used for Firecrawl extraction and by the Avvo, Glassdoor and DoorDash scrapers. |
enableCrossValidation | boolean | true | No | Work out the most likely correct NAP from all sources |
enableAiAnalysis | boolean | true | No | Use Claude to write recommendations and fix suggestions (needs anthropicApiKey) |
anthropicApiKey | string | - | No | Your Anthropic API key for the AI analysis |
platforms | array | - | No | Only check these directories (leave empty to use the scan mode's list). Named directories are checked whatever the industry. |
providedUrls | object | - | No | Known listing URLs by directory name, e.g. {"Yelp": "https://www.yelp.com/biz/...", "TikTok": "https://www.tiktok.com/@..."}. Each saved URL is reported, and the directory's check opens it directly where it can. |
webhookUrl | string | - | No | URL to POST the results to when the run completes |
demoMode | boolean | false | No | Return a labeled sample report without scraping |
Output
One dataset item per run with the business, the cross-validated NAP, a score, and mergedResults: one row per directory. Every row has the same fields, null when unknown:
| Field | Meaning |
|---|---|
platform | Directory name |
status | See the table below |
url | The listing URL |
foundName, foundAddress, foundPhone, foundWebsite | What the listing shows |
nameMatch, addressMatch, phoneMatch | true / false when compared, null when that field could not be compared |
source | direct (the directory itself: our scraper, its own search or its phone lookup), google (Google's results for the directory; its pages were not read), moz (Moz Local's report) or provided (a saved URL, or the Google Business Profile from the input) |
checkMethod | dedicated_scraper, site_search, phone_lookup, search (Google), browser, saved_url, firecrawl, moz or input |
issues | Mismatches, duplicates and other locations of the brand, as sentences (an empty list when none) |
rating, reviewCount, confidence, error, relevanceReason, isRelevant, checkedAt | Extra detail |
| Status | Meaning |
|---|---|
correct | Listing found, and its name, address and phone were all compared and all match |
incorrect | Listing found, and at least one of name, address or phone does not match (see issues) |
found | Listing found, but not all of name, address and phone could be compared (issues says which). This includes saved URLs that were not read and directories checked through Google's results |
missing | The check reached the directory (or got a clear answer from Google) and found no listing |
error | The check failed or the site blocked it; not verified either way |
duplicate / incomplete | Reported by the Moz scan |
n/a | The directory does not apply to this business's industry; not checked (reason in relevanceReason) |
not_checked | This scan does not check the directory, or could not tell this business's listing from another location's (reason in relevanceReason) |
summary.totalChecked and the score count only checked directories, and summary.correct, incorrect, found, missing, errors (not verified), duplicates and incomplete add up to it; the final status message gives the same counts. summary.notApplicable, summary.notChecked and summary.possibleMatches count the directories that were skipped or wait for review. The dataset's "Citation Overview" view shows these counts per scan.
The item also says whether the run's maximum cost per run left anything out (see "Set your maximum cost per run"):
| Field | Meaning |
|---|---|
budgetLimited | true when the maximum cost per run left some directories unchecked, or checked only through Google's results |
directoriesSkippedForBudget | How many directories are not_checked because their scraper's sub-run did not fit in the maximum |
directoriesCheckedThroughGoogleForBudget | How many directories were checked through Google's results instead of our scraper, for the same reason |
minimumMaxTotalChargeUsd | The lowest maximum cost per run at which this scan usually checks every directory, its sub-runs taking turns |
recommendedMaxTotalChargeUsd | The maximum cost per run that lets every sub-run of this scan start at once |
maxTotalChargeUsd | This run's maximum cost per run |
Pricing
This Actor uses pay-per-event billing. A run charges:
| Event | When it is charged | Price |
|---|---|---|
| Actor start | Once when the run starts, one event per GB of memory (minimum one). At the default 4 GB of memory a run starts at $0.40 | $0.10 per GB |
| Quick scan | Once per completed quick scan | $0.10 |
| Standard scan | Once per completed standard scan | $0.15 |
| Full scan | Once per completed deep or god-mode scan | $0.25 |
| Result | Each item written to the default dataset | $0.00001 |
The price list also shows per-citation, cross-validation and AI analysis events; this version does not charge them. Sample (demo) runs charge no scan event.
Dedicated scrapers run as separate Actors on your Apify account and are billed at their own prices: in our scans a sub-run charged $0.10 to $0.45, mostly its start event, so a standard scan's six sub-runs came to about $1.60. When this run has a maximum cost per run, the sub-runs are kept inside what is left of it after this Actor's own charges: each sub-run starts with its own maximum cost (at least the minimum that scraper requires, usually $1), a sub-run that does not fit waits for a running one to finish, and a directory whose sub-run still does not fit is reported as not_checked with the reason, or checked through Google's results where the directory has that check. The sub-runs take turns in the scan's order, so a scraper with a $1 minimum is not crowded out by smaller ones started after it. A finished sub-run's actual charge, read from its run record, is what stays counted, not its cap. So with the minimum of $3, a quick or standard scan runs two or three sub-runs at a time and usually checks every directory; see "Set your maximum cost per run" for each scan mode. The scan starts each sub-run and then follows it by its run ID, so a dropped connection while it waits does not lose a sub-run that finished. The directory searches, phone lookups and Google checks run inside this Actor and cost nothing extra. Skipped directories (n/a, not_checked) start no sub-run. Firecrawl and Anthropic usage is billed by those services to your keys.
Troubleshooting
A directory shows n/a but the business is listed there
Set industry to the business's trade or Google Business Profile category, add the directory to platforms, or save its URL in providedUrls.
Directories show not_checked "skipped for this run's maximum cost per run"
Your maximum cost per run was too low for those directories' scraper sub-runs. Raise it to at least the amount in minimumMaxTotalChargeUsd, or to recommendedMaxTotalChargeUsd to run every scraper at once (see the table under "Set your maximum cost per run"), and run the scan again. You are charged only for what the scan uses.
A directory shows error
The directory blocked the check or the scraper failed. It is not verified either way. Running again later often works.
"API error 403" or "Unauthorized" from Firecrawl or Anthropic
The key is invalid, expired, or lacks access. Check the key and your account.
No results or empty dataset
Check the run log. Common causes: missing business name, city or state; an invalid providedUrls value (it must be an object, not a string).
How do I test without keys?
Run the Actor without business details, or set demoMode to true. It returns a labeled sample report in the live output format. The sample item carries demo: true and a _notice field, and sample runs charge no scan event. Provide a business name, city and state for a real audit; keys are only needed for the optional Firecrawl and AI parts.
Built by John Rippy | Actor Arsenal