sfoln/local-business-audit · SEO tools, Lead generation, Automation On request
Audit a local business by name and city, place ID or Maps link: Google Business Profile completeness, review stats, local rank for up to 3 keywords with top competitors, website SEO, speed, mobile and NAP match, a 0–100 score and fixes. $35 per 1,000 audits.
Run a local SEO audit of any business on Google Maps: give a business name and city, a Google place ID, a CID or a Google Maps link, and the Actor reads its Google Business Profile, checks where it ranks in Google's local results for up to 3 keywords, audits the website linked from the profile and returns one scored JSON record: profile completeness (claimed, categories, hours, photos, description, attributes), review count, rating and star distribution, local rank with the 3 best-placed competitors, website SEO, speed, mobile setup, HTTPS, LocalBusiness structured data and NAP consistency (does the website show the profile's name, address and phone?), booking and chat widgets, ad pixels, domain age and e-mail authentication, plus an overall 0–100 score, a letter grade and a list of issues with a recommendation each. Built for local SEO and web-design agencies prospecting and reporting, franchise managers checking locations, and AI agents asked "how is this business doing on Google?".
Price
Price per delivered record
Event
Price
Per 1,000
Charged for
Local business audit local-audit
$0.035
$35 / 1,000
Charged once per business whose Google Business Profile was found: profile completeness, review stats, local rank for up to 3 keywords with competitors, website SEO / speed / mobile / NAP audit, domain and e-mail setup, scores and recommended fixes.
Apify free plan: up to 5 items per run. Paid plans have no per-run cap; set maxTotalChargeUsd to cap spend.
Run
Call it from code, an agent or the Console
This API is private on Apify for now. Email us and we will publish it for you, usually within two working days. The calls below work once it is public. contact@sfoln.com
POST https://api.apify.com/v2/actors/sfoln~local-business-audit/runs?maxTotalChargeUsd=1
GET https://api.apify.com/v2/actor-runs/{runId} # until status is SUCCEEDED
GET https://api.apify.com/v2/datasets/{defaultDatasetId}/items?format=json
Authenticate with an Apify API token. MCP clients can instead sign in with OAuth when prompted. Example prompt for an agent: Audit the local SEO of Katz's Delicatessen in New York: how complete is its Google Business Profile, where does it rank for "deli", is its website consistent with the profile, and what should it fix first?
Input
Input fields
List businesses by name and city, Google place ID, CID or Google Maps link. Each business produces one audit record.
Field
Type
Default
Meaning
businesses *
array
required
Businesses One per line: a business name ("Joe's Pizza Broadway"), a Google Maps link of the place, a place ID ("ChIJ…" or "place_id:…") or a CID ("cid:2946633002421908862" or the bare number of 15+ digits, always as a string: JSON numbers that large lose digits). Override the location per line with "name | location". Objects may also set per-business keywords: {"name": "…", "location": "…", "keywords": ["…"]}. Accounts on the Apify free plan can process up to 5 businesses per run.
location
string
—
Location Where to look up business names: a DataForSEO location name ("New York,New York,United States") or numeric location code (2840 = United States). For place IDs, CIDs and Maps links it only sets the regional context.
keywords
array
—
Rank keywords Up to 3 searches to check the business's local rank for, e.g. "emergency plumber". Each is searched as "<keyword> in <city of the business>" on Google's local results. Empty: the profile's primary category (one search).
checkRankings
boolean
true
Check local rank Search Google's local results for each keyword and report the business's position and the top 3 competitors.
checkWebsite
boolean
true
Audit the website Read the website linked from the profile (homepage and contact page): SEO, speed, mobile, HTTPS, LocalBusiness data, NAP consistency with the profile, booking and chat widgets, ad pixels, domain age and e-mail authentication.
languageCode
string
"en"
Language code Language of the profile data and of the local-rank searches (ISO code such as en, de, es).
maxItems
integer
1000
Max businesses Safety cap on the number of businesses audited in this run. Range 1–10000.
concurrency
integer
3
Concurrency How many businesses are audited in parallel. Range 1–8.
includeRaw
boolean
false
Include raw upstream response Attach the unmodified business profile and local results to each record (larger output).
Records land in the run's dataset; a synchronous call returns them directly. Each has a status (ok is charged; everything else is free) and a charged flag. The run's OUTPUT record totals items and charges.
Field
Type
Meaning
input
object
Input { lookup, location?, keywords? }: the business as given (name, cid:…, place_id:… or Google Maps link).
status
string
Status ok | not_found | error | skipped_invalid | skipped_budget | skipped_free_plan | skipped_unmetered
charged
boolean
Charged Whether this record incurred a local-audit charge.
chargedEvent
string
Charged event local-audit (present only when charged).
chargedCount
integer
Events charged Events actually charged when the charge came back short (present only then).
source
string
Source Upstream data sources.
fetchedAt
string
Fetched at ISO timestamp.
error
object
Error { code, message, provider?, status? } when status is not ok: not_found (no Google Business Profile for the name / id), invalid_input (unreadable Maps link), plus the runtime codes (budget_exhausted, free_plan_limit, unmetered, aborted, charge_failed, record_too_large, invalid_record, dataset_push_failed) and upstream codes (auth, insufficient_credits, rate_limit, timeout, network, server, client, invalid_response).
warnings
array
Warnings Parts that failed or were skipped: rank searches, a website that refused the request, RDAP.
lookupKind
string
Lookup kind cid, place_id or keyword (business name).
location
string
Location Location used for the lookup.
found
boolean
Found A Google Business Profile was found.
businessName
string | null
Business name Name on the Google Business Profile.
category
string | null
Category Primary category.
additionalCategories
array
Secondary categories Further categories of the profile.
address
string | null
Address Formatted address.
city
string | null
City City of the address.
postalCode
string | null
Postal code Postal code of the address.
region
string | null
Region State or region.
countryCode
string | null
Country ISO 3166-1 alpha-2 country code.
phone
string | null
Phone Phone number as shown on the profile.
phoneE164
string | null
Phone (E.164) The profile's phone in E.164 (+12175550142).
website
string | null
Website Website linked from the profile.
domain
string | null
Domain Host of the website (without www.).
cid
string | null
CID Google customer id of the place.
placeId
string | null
Place ID Google place id.
googleMapsUrl
string | null
Google Maps Link to the place on Google Maps.
latitude
number | null
Latitude Latitude of the place.
longitude
number | null
Longitude Longitude of the place.
isClaimed
boolean | null
Claimed The owner has claimed the profile.
currentStatus
string | null
Status on Google open, closed (right now), temporarily_closed or closed_forever.
rating
number | null
Rating Average star rating.
reviewCount
integer
Reviews Number of Google reviews.
auditScore
integer
Audit score Overall score 0–100: 35% profile completeness, 30% website, 20% reviews, 15% local rank (sections not assessed are left out).
grade
string
Grade A (90+), B (75+), C (60+), D (45+), E (25+), F.
scores
object
Scores { overall, profile, reviews, visibility, website } 0–100 (visibility / website null when not assessed; website 0 without a website or with a social / directory page as the website).
NAP consistency { name { gbp, site, score, match }, phone { gbp, site[], match }, address { gbp, postalCodeFound, streetFound, cityFound, match }, consistent, score }: the profile's name, address and phone compared with the website.
presence
object | null
Domain and e-mail { domain, domainCreatedAt, domainAgeDays, registrar, mailProvider, hasMailServer, spf, dmarcPolicy, spfDmarcLookup }: spfDmarcLookup failed = the SPF / DMARC lookup failed (spf null, dmarcPolicy unknown); null for a website on a shared platform domain (wixsite.com, myshopify.com …) or without a website of its own.
issues
array
Issues { severity (high | medium | low), area (profile | reviews | visibility | nap | website | presence), code, finding, recommendation }, most severe first.
issueCounts
object
Issue counts { high, medium, low }.
sections
object
Sections State of each part: profile ok; visibility ok | partial | error | skipped | off; website ok | none | social (a social or directory page as the website, not audited) | blocked | error | off; presence ok | partial | skipped | off.
Example recordExample record
{
"input": {
"lookup": "cid:1234567890123456789",
"location": "Springfield,Illinois,United States",
"keywords": [
"dentist",
"emergency dentist"
]
},
"lookupKind": "cid",
"location": "Springfield,Illinois,United States",
"found": true,
"businessName": "Maple Street Dental",
"category": "Dentist",
"additionalCategories": [
"Cosmetic dentist"
],
"address": "1200 S Maple St, Springfield, IL 62704",
"city": "Springfield",
"postalCode": "62704",
"region": "Illinois",
"countryCode": "US",
"phone": "+1217-555-0142",
"phoneE164": "+12175550142",
"website": "https://www.maplestreetdental.example/",
"domain": "maplestreetdental.example",
"cid": "1234567890123456789",
"placeId": "ChIJmapleStreetDental0001",
"googleMapsUrl": "https://www.google.com/maps?cid=1234567890123456789",
"latitude": 39.7817,
"longitude": -89.6501,
"isClaimed": false,
"currentStatus": "open",
"rating": 4.1,
"reviewCount": 23,
"auditScore": 69,
"grade": "C",
"scores": {
"overall": 69,
"profile": 60,
"reviews": 57,
"visibility": 50,
"website": 96
},
"profile": {
"completeness": 60,
"checks": [
{
"check": "claimed",
"label": "Profile claimed by the owner",
"ok": false,
"points": 0,
"maxPoints": 15
},
{
"check": "primaryCategory",
"label": "Primary category",
"ok": true,
"points": 10,
"maxPoints": 10
},
{
"check": "photos",
"label": "10 or more photos",
"ok": false,
"points": 5,
"maxPoints": 10
}
],
"description": "Family dentist in Springfield.",
"workHours": {
"monday": [
"08:00-17:00"
],
"tuesday": [
"08:00-17:00"
]
},
"workHoursSummary": "Mon 08:00-17:00; Tue 08:00-17:00; Wed 08:00-17:00; Thu 08:00-17:00; Fri 08:00-13:00; Sat closed; Sun closed",
"totalPhotos": 6,
"logo": null,
"mainImage": "https://lh5.googleusercontent.com/p/maple-street-dental-main=w648-h240-k-no",
"attributes": [
"has_wheelchair_accessible_entrance",
"accepts_new_patients"
],
"services": 0,
"bookOnlineUrl": null,
"priceLevel": null,
"peopleAlsoSearch": [
"Lincoln Park Dental Care"
]
},
"reviews": {
"rating": 4.1,
"count": 23,
"distribution": {
"1": 3,
"2": 1,
"3": 1,
"4": 4,
"5": 14
},
"positiveShare": 0.78,
"negativeShare": 0.17,
"topics": {
"cleaning": 12,
"front desk": 5
},
"score": 57
},
"visibility": {
"keywords": [
{
"keyword": "dentist",
"query": "dentist in Springfield, Illinois",
"rank": 2,
"resultsCount": 20,
"competitors": [
{
"rank": 1,
"name": "Lincoln Park Dental Care",
"rating": 4.8,
"reviewCount": 412,
"category": "Dentist",
"domain": "lincolnparkdental.example",
"cid": "9876543210987654321"
},
{
"rank": 3,
"name": "Capitol City Smiles",
"rating": 4.6,
"reviewCount": 158,
"category": "Cosmetic dentist",
"domain": "capitolcitysmiles.example",
"cid": "1111111111111111111"
},
{
"rank": 4,
"name": "Prairie Family Dentistry",
"rating": 4.9,
"reviewCount": 87,
"category": "Dentist",
"domain": null,
"cid": "2222222222222222222"
}
],
"error": null
},
{
"keyword": "emergency dentist",
"query": "emergency dentist in Springfield, Illinois",
"rank": null,
"resultsCount": 20,
"competitors": [
{
"rank": 1,
"name": "Capitol City Smiles",
"rating": 4.6,
"reviewCount": 158,
"category": "Cosmetic dentist",
"domain": "capitolcitysmiles.example",
"cid": "1111111111111111111"
},
{
"rank": 2,
"name": "Springfield Emergency Dental",
"rating": 4.3,
"reviewCount": 64,
"category": "Emergency dental service",
"domain": "springfieldemergencydental.example",
"cid": "3333333333333333333"
}
],
"error": null
}
],
"bestRank": 2,
"score": 50
},
"websiteAudit": {
"url": "https://www.maplestreetdental.example/",
"finalUrl": "https://www.maplestreetdental.example/",
"status": 200,
"https": true,
"sslValid": true,
"sslIssuer": "Let's Encrypt",
"sslDaysLeft": 75,
"mobileFriendly": true,
"title": "Maple Street Dental | Family Dentist in Springfield, IL",
"metaDescription": "Gentle family and cosmetic dentistry in Springfield, Illinois. New patients welcome, same-week appointments and evening hours. Book online today.",
"h1": "Family dentistry in Springfield",
"cms": null,
"technologies": [
"Facebook Pixel",
"Google Tag Manager",
"Let's Encrypt",
"Open Graph"
],
"bookingWidgets": [
"Zocdoc"
],
"chatWidgets": [],
"adPixels": [
"Meta Pixel"
],
"analytics": [
"Google Tag Manager"
],
"runsAds": true,
"localBusinessSchema": {
"present": true,
"types": [
"Dentist"
],
"name": "Maple Street Dental",
"telephone": "+1-217-555-0142",
"address": "1200 South Maple Street, 62704 Springfield, IL, US",
"hasOpeningHours": true,
"hasGeo": false
},
"phonesOnSite": [
"+12175550142"
],
"hasClickToCall": true,
"emailsOnSite": [
"maplestreetdental.frontdesk@gmail.com"
],
"socials": {
"facebook": "https://www.facebook.com/maplestreetdental",
"instagram": "https://www.instagram.com/maplestreetdental"
},
"copyrightYear": 2021,
"staleSite": true,
"lastModified": null,
"performance": {
"ttfbMs": 420,
"htmlKb": 38.2,
"compressed": true,
"requestEstimate": 31,
"renderBlockingScripts": 0
},
"scores": {
"seo": 97,
"performance": 100,
"local": 90
},
"pagesRead": [
"https://www.maplestreetdental.example/",
"https://www.maplestreetdental.example/contact/"
]
},
"nap": {
"name": {
"gbp": "Maple Street Dental",
"site": "Maple Street Dental",
"score": 1,
"match": true
},
"phone": {
"gbp": "+12175550142",
"site": [
"+12175550142"
],
"match": true
},
"address": {
"gbp": "1200 S Maple St, Springfield, IL 62704",
"postalCodeFound": true,
"streetFound": true,
"cityFound": true,
"match": true
},
"consistent": true,
"score": 100
},
"presence": {
"domain": "maplestreetdental.example",
"domainCreatedAt": "2014-03-02T10:00:00Z",
"domainAgeDays": 4609,
"registrar": "Example Registrar LLC",
"mailProvider": "Google Workspace",
"hasMailServer": true,
"spf": true,
"dmarcPolicy": null,
"spfDmarcLookup": "ok"
},
"issues": [
{
"severity": "high",
"area": "profile",
"code": "profile_unclaimed",
"finding": "The profile is not claimed by the business (anyone can suggest edits and the owner cannot reply to reviews).",
"recommendation": "Claim and verify the profile in Google Business Profile Manager so the owner controls its details, posts and review replies."
},
{
"severity": "high",
"area": "visibility",
"code": "visibility_not_ranking",
"finding": "Not among Google's top 20 local results for \"emergency dentist in Springfield, Illinois\".",
"recommendation": "Build relevance for \"emergency dentist\": use it in the categories, description and services of the profile and in the website's homepage title and text, and collect reviews that mention it."
},
{
"severity": "medium",
"area": "profile",
"code": "profile_short_description",
"finding": "The business description is only 30 characters.",
"recommendation": "Add a 250–750 character description naming the main services and the area served."
},
{
"severity": "medium",
"area": "profile",
"code": "profile_few_photos",
"finding": "The profile has 6 photos; profiles with 10+ get more clicks.",
"recommendation": "Upload at least 10 recent photos (outside, inside, team, work) and add new ones every month."
}
],
"issueCounts": {
"high": 2,
"medium": 3,
"low": 5
},
"sections": {
"profile": "ok",
"visibility": "ok",
"website": "ok",
"presence": "ok"
},
"status": "ok",
"charged": true,
"chargedEvent": "local-audit",
"source": "dataforseo+serper+website",
"fetchedAt": "2026-10-15T12:00:00.000Z"
}
FAQ
Questions
What does one audit check?
The Google Business Profile (claimed status, categories, phone, website, hours, description, photos, attributes, services), review counts and the star distribution, the business's position in Google's local results for up to 3 keywords with the 3 best-placed competitors, and the website linked from the profile: HTTPS and certificate, mobile viewport, title, description and H1, speed proxies, LocalBusiness structured data, tap-to-call, freshness, booking and chat widgets, ad pixels, and whether its name, address and phone match the profile. Every gap becomes an issue with a recommendation.
How are the scores calculated?
Profile completeness is a 100-point checklist; reviews combine the rating (60%) and the review volume (40%); local rank gives 100 for the top 3, 80 for 4–5, 60 for 6–10 and 40 below; the website score is 45% SEO, 25% speed and 30% local signals (HTTPS, LocalBusiness data, tap-to-call, freshness, NAP). The overall score weighs the profile 35%, the website 30%, reviews 20% and local rank 15%, leaving out sections that could not be assessed.
What if the business is not found?
Nothing is charged. Names work best with the city ("Joe's Pizza Broadway New York") or a location; place IDs, CIDs and Google Maps links of the place are exact.