Local Business Data Extractor (NAP, hours, geo) avatar

Local Business Data Extractor (NAP, hours, geo)

Under maintenance

Pricing

Pay per usage

Go to Apify Store
Local Business Data Extractor (NAP, hours, geo)

Local Business Data Extractor (NAP, hours, geo)

Under maintenance

Extract normalized local-business data — name, type, phone, email, full address, lat/long, opening hours, price range, rating — from public pages via JSON-LD (LocalBusiness subtypes, Organization), microdata, and OpenGraph. HTML-only, fast, structured ok/error output.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

Tommy G

Tommy G

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

6 days ago

Last modified

Share

Local Business Extractor (Apify Actor)

Give it any public business / venue page URL and get back clean, normalized LocalBusiness data — name, business type, contact details, full address with geo coordinates, opening hours, price range, and aggregate rating — pulled from schema.org LocalBusiness (and subtypes like Restaurant / Store) in JSON-LD and microdata. HTML-only (no headless browser) so it's fast and cheap. Ideal for local-business directories, lead lists, and store-locator / map datasets.

What it extracts

For each page it returns one flat record with:

  • name, legal_name, business_type, description
  • telephone, email, url, image
  • Address: street_address, locality, region, postal_code, country, address_full
  • Geo: latitude, longitude
  • opening_hours[], price_range, founding_date, same_as[] (linked social/profile URLs)
  • Ratings: rating_value, rating_best, rating_count

Plus control keys present on every row (ok and error alike, for clean buyer tables):

status, requested_url, final_url, http_status, redirected, found, complete, page_type, source, render_required, fields_found, error, extracted_at
.

Input

{ "startUrls": [{ "url": "https://example.com/locations/downtown" }], "maxConcurrency": 5, "maxPages": 100 }

maxPages capped at 200, maxConcurrency at 20 (cost guard).

Output — one STABLE record per URL (ok and error rows share the shape)

{
"status": "ok",
"requested_url": "https://example.com/locations/downtown",
"final_url": "https://example.com/locations/downtown",
"http_status": 200,
"found": true,
"complete": true,
"page_type": "localbusiness",
"source": "json-ld",
"name": "Acme Coffee Downtown",
"legal_name": "Acme Coffee LLC",
"business_type": "CafeOrCoffeeShop",
"description": "Specialty coffee in the heart of downtown.",
"telephone": "+1-212-555-0100",
"email": "hello@acmecoffee.example",
"url": "https://acmecoffee.example",
"image": "https://example.com/img/store.jpg",
"street_address": "123 Main St",
"locality": "New York",
"region": "NY",
"postal_code": "10001",
"country": "US",
"address_full": "123 Main St, New York, NY 10001, US",
"latitude": 40.7128,
"longitude": -74.006,
"opening_hours": ["Mo-Fr 07:00-19:00", "Sa-Su 08:00-17:00"],
"price_range": "$$",
"rating_value": 4.6,
"rating_best": 5,
"rating_count": 312,
"same_as": ["https://instagram.com/acmecoffee"],
"fields_found": ["name", "telephone", "address_full", "rating_value"],
"extracted_at": "2026-05-29T..."
}

found:false means no LocalBusiness markup was present (e.g. a JS-rendered locator widget). Failed fetches return the same keys with status:"error" + error.

Use cases

  • Local-business directories — assemble structured listings (name, type, contact, hours, rating).
  • Lead lists — pull public phone/email/address for businesses across a set of pages.
  • Store-locator / map datasets — get geo coordinates + opening hours for mapping.

Notes / safety

  • Reads only public schema.org business markup — facts-only, only contact details the page itself publicly publishes; no raw page bodies stored.
  • SSRF-guarded (scheme + private/metadata IP block + redirect re-check), robots-respecting, rate-limited, cost-capped — all via the shared src/lib/actor_runner.js.
  • HTML-only: client-rendered pages that inject business JSON via JS return found:false (no server-side markup to read). Core logic in src/extract.js (pure, unit-tested).

Run locally / test

npm install
npm test # unit tests on the pure extractor (node:test)

Publish to Apify (account-holder's step)

$npm install -g apify-cli && apify login && apify push

Keep it free initially; enable pricing later via the adult account-holder once it shows repeat organic usage and clears a margin gate.