Citation God Mode - NAP Consistency Checker avatar

Citation God Mode - NAP Consistency Checker

Pricing

from $0.01 / 1,000 results

Go to Apify Store
Citation God Mode - NAP Consistency Checker

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

The Howlers

Maintained by Community

Actor stats

3

Bookmarked

27

Total users

1

Monthly active users

4 hours ago

Last modified

Security

Limited permissions

Share

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 modeLowest 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.50about $1.45
standard$3 (the Actor's minimum)$5.50about $2.15
deep$3.50; $4 for contractors and home services$6.50 to $7.50; $9.50 for contractors and home servicesabout $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 agenciesabout $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/a and 40 are checked.
  • 18 list only one kind of business, and are checked only for that kind (n/a otherwise).
  • 3 are not checked and are always reported as not_checked: eLocal, Kompass and YellowBot (the reason for each is in relevanceReason).

The scan mode picks which directories are in the scan, and the business's industry decides which industry directories stay in:

Scan modeDirectories in the modeChecked for a business in one industry
quick77
standard1413, or 14 for a restaurant, hotel or attraction
deep5141, plus up to 3 for its industry (up to 44)
god-mode6241, 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: correct when the name is an accepted short form ("Deli" for "Delicatessen", "St." for "Saint", "Bros" for "Brothers"), incorrect with 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 in providerNames or, 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 as found because its name is the practitioner's; when its address or phone does not match, it is incorrect and 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_checked when 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, never missing.
  • 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 is error.

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 also not_checked, as are Avvo and Glassdoor when no firecrawlApiKey is 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

ParameterTypeDefaultRequiredDescription
businessNamestring-YesThe exact business name to check
streetAddressstring-NoStreet address (e.g., '123 Main St Suite 100'). The Moz scan needs it.
citystring-YesCity name
statestring-YesState abbreviation (e.g., 'FL', 'CA')
zipCodestring-No5-digit ZIP code
phonestring-NoBusiness phone number in any format. Without it, phone numbers are not compared.
websitestring-NoBusiness website
industrystring-NoThe 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".
providerNamesarray-NoThe 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.
googlePlaceIdstring-NoGoogle Maps Place ID. When given, the Google Business Profile is the source of truth and marked correct.
scanModestring"standard"Noquick (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".
enableMozScanbooleantrueNoRun the Moz Local listing check (free; its report covers about a dozen major directories)
enableDirectScrapebooleantrueNoCheck directories directly for detailed NAP data
useDedicatedScrapersbooleantrueNoUse 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.
enableFirecrawlbooleantrueNoUse Firecrawl for directories without a dedicated scraper (needs firecrawlApiKey)
firecrawlApiKeystring-NoYour Firecrawl API key. Used for Firecrawl extraction and by the Avvo, Glassdoor and DoorDash scrapers.
enableCrossValidationbooleantrueNoWork out the most likely correct NAP from all sources
enableAiAnalysisbooleantrueNoUse Claude to write recommendations and fix suggestions (needs anthropicApiKey)
anthropicApiKeystring-NoYour Anthropic API key for the AI analysis
platformsarray-NoOnly check these directories (leave empty to use the scan mode's list). Named directories are checked whatever the industry.
providedUrlsobject-NoKnown 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.
webhookUrlstring-NoURL to POST the results to when the run completes
demoModebooleanfalseNoReturn 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:

FieldMeaning
platformDirectory name
statusSee the table below
urlThe listing URL
foundName, foundAddress, foundPhone, foundWebsiteWhat the listing shows
nameMatch, addressMatch, phoneMatchtrue / false when compared, null when that field could not be compared
sourcedirect (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)
checkMethoddedicated_scraper, site_search, phone_lookup, search (Google), browser, saved_url, firecrawl, moz or input
issuesMismatches, duplicates and other locations of the brand, as sentences (an empty list when none)
rating, reviewCount, confidence, error, relevanceReason, isRelevant, checkedAtExtra detail
StatusMeaning
correctListing found, and its name, address and phone were all compared and all match
incorrectListing found, and at least one of name, address or phone does not match (see issues)
foundListing 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
missingThe check reached the directory (or got a clear answer from Google) and found no listing
errorThe check failed or the site blocked it; not verified either way
duplicate / incompleteReported by the Moz scan
n/aThe directory does not apply to this business's industry; not checked (reason in relevanceReason)
not_checkedThis 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"):

FieldMeaning
budgetLimitedtrue when the maximum cost per run left some directories unchecked, or checked only through Google's results
directoriesSkippedForBudgetHow many directories are not_checked because their scraper's sub-run did not fit in the maximum
directoriesCheckedThroughGoogleForBudgetHow many directories were checked through Google's results instead of our scraper, for the same reason
minimumMaxTotalChargeUsdThe lowest maximum cost per run at which this scan usually checks every directory, its sub-runs taking turns
recommendedMaxTotalChargeUsdThe maximum cost per run that lets every sub-run of this scan start at once
maxTotalChargeUsdThis run's maximum cost per run

Pricing

This Actor uses pay-per-event billing. A run charges:

EventWhen it is chargedPrice
Actor startOnce 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 scanOnce per completed quick scan$0.10
Standard scanOnce per completed standard scan$0.15
Full scanOnce per completed deep or god-mode scan$0.25
ResultEach 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