Herold.at Scraper - Austrian Businesses, Contacts & Reviews
Pricing
from $0.80 / 1,000 results
Herold.at Scraper - Austrian Businesses, Contacts & Reviews
From $0.80/1K. Scrape Herold.at business listings across Austria into clean JSON. Extract names, addresses, GPS, phone numbers, emails, websites, ratings, reviews, opening hours, payment methods, and founding dates by category, city, or region.
Pricing
from $0.80 / 1,000 results
Rating
5.0
(1)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
9
Total users
5
Monthly active users
4 days ago
Last modified
Categories
Share
Herold.at Scraper: Austrian Business Listings, Contacts and Reviews
Herold.at Scraper turns Herold.at, Austria's largest business directory, into a clean structured dataset. Get company names, full addresses, phone numbers, emails, websites, ratings, reviews, opening hours, payment methods and founding dates for any category in any Austrian city or region. Build a search from categories and locations, or paste a Herold.at search URL directly, then export the results to JSON, CSV or Excel, or read them through the API.
Why This Scraper?
- Two ways to start. Pick categories and locations from the input panel, or paste any Herold.at search URL straight from your browser.
- Rich contact data on every listing, even without detail fetching. Name, full address, phone, email, website, rating and verified status all come from the search results page alone.
- Optional detail enrichment. Turn on Fetch detail pages to add GPS coordinates, opening hours, payment methods, founding date and the full review list for each listing.
- Multi-search batching. Give it several categories and several locations and it searches every combination in one run.
- Automatic forward pagination. The actor walks result pages until it reaches the natural end of the search, or the limit you set, whichever comes first.
- Built for recurring monitoring. Incremental mode returns only new and changed listings on repeat runs, and a refused or empty response is retried automatically with a fresh session.
- Post-fetch filters. Keep only verified listings, only rated listings, or only listings above a minimum rating, without changing the underlying search.
Use Cases
- Local lead generation: build call lists and email lists for a category and city, complete with phone numbers and websites.
- CRM enrichment: cross-check existing company records against Herold.at for updated addresses, phone numbers and ratings.
- Market and competitor research: measure how many businesses exist per category and region, and how they compare on ratings and reviews.
- Directory and aggregator sites: feed a local business directory or comparison site with structured, current listings.
- Recurring monitoring: track a category or region on a schedule and get notified only about new, changed or closed listings.
Data You Get
Sample shape, values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
id | "00000" (Herold.at listing ID) |
url | "https://www.herold.at/gelbe-seiten/wien/00000/sample-company/" |
name | "Sample Company" |
category | "restaurant" |
regionSlug | "wien" |
isVerified | true ("Verifiziert" badge on the listing) |
streetAddress | "Sample Street 1" |
postalCode | "1010" |
addressLocality | "Wien" |
addressRegion | "Wien" |
addressCountry | "AT" |
telephone | "+43 1 0000000" |
email | "contact@example.com" (when the company supplied one) |
website | "https://example.com" (when the company supplied one) |
logoUrl | "https://images.herold.at/optimize?url=...&width=320" |
ratingValue | 4.8 (average rating, 1 to 5) |
ratingCount | 42 |
branchCode | "00000" |
latitude | 48.0000 (requires Fetch detail pages) |
longitude | 16.0000 (requires Fetch detail pages) |
foundingDate | "2020" (requires Fetch detail pages) |
paymentAccepted | ["Cash", "Card"] (requires Fetch detail pages) |
openingHours | [{ "day": "Monday", "opens": "09:00", "closes": "18:00" }] (requires Fetch detail pages) |
reviews | [{ "author": "Sample Reviewer", "body": "Sample review text.", "rating": 5 }] (requires Fetch detail pages) |
scrapedAt | "2026-01-01T00:00:00.000Z" |
Every listing also carries imageCount, bestRating and worstRating from the search results, whether or not detail pages are fetched. Detail-enriched listings additionally carry description, reviewCount, breadcrumb, services (tag chips such as cuisine or amenities) and branchen (this company's own category memberships on Herold.at). In Incremental mode, every record additionally carries changeType (NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED), changedFields, firstSeenAt and lastSeenAt.
How to Use
- Pick a mode:
search(categories and locations) orurl(paste a prepared Herold.at search link). - In search mode, fill in one or more category slugs and, optionally, one or more location slugs. Leave locations empty to search all of Austria for that category.
- Turn on Fetch detail pages if you need GPS, opening hours, payment methods, founding date or reviews, and set Max pages or Max listings to control run size and cost.
- Click Start. Download the dataset as JSON, CSV or Excel, or read it through the API.
Search mode, single category and location, fast:
{"mode": "search","categories": ["restaurant"],"locations": ["wien"],"maxPages": 5,"maxListings": 100}
Search mode, multiple categories and locations, with detail enrichment:
{"mode": "search","categories": ["elektriker", "installateur"],"locations": ["wien", "salzburg", "bregenz"],"fetchDetails": true,"maxPages": 3,"maxListings": 200}
Search mode, Austria-wide for a category, no location filter:
{"mode": "search","categories": ["zahnarzt"],"locations": [],"maxPages": 10}
URL mode, paste a prepared search link:
{"mode": "url","urls": ["https://www.herold.at/gelbe-seiten/wien/restaurant/","https://www.herold.at/gelbe-seiten/salzburg/elektriker/"],"maxPages": 5,"maxListings": 100}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/herold-at-scraper").call(run_input={"mode": "search", "categories": ["restaurant"], "locations": ["wien"]})for listing in client.dataset(run["defaultDatasetId"]).iterate_items():print(listing["name"], listing["telephone"], listing["website"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/herold-at-scraper').call({ mode: 'search', categories: ['restaurant'], locations: ['wien'] });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
Finding category and location slugs
The simplest way to find a valid slug is to browse Herold.at yourself: open the gelbe-seiten section of herold.at, click into any category, and copy the slug from the URL path, for example restaurant or elektriker. Do the same for a location by opening a search result page and reading the first path segment, for example wien. Not every location and category combination has its own page: cities such as Graz, Linz, Innsbruck and Klagenfurt commonly return no results on a combined location and category URL, even though they appear in listing addresses. Leave Locations empty to search all of Austria for a category, then filter the dataset by addressLocality afterwards if you need one specific city.
Resume and recurring updates
resumeFromRunId and Incremental mode solve different problems.
- Resume (
resumeFromRunId) continues one interrupted run: paste its run or dataset ID and this run skips every listingidalready saved there, appending only the new ones. - Incremental mode (
incrementalMode) monitors the same search across separate scheduled runs. The actor keeps its own baseline in a private key-value store, keyed by State key or by an automatic hash of mode, categories, locations, urls, the post-fetch filters and Fetch detail pages, so changing Max listings or Max pages tomorrow still matches the same baseline. Every listing is classifiedNEW,UPDATED(withchangedFields),UNCHANGED,REAPPEAREDorEXPIRED.UNCHANGEDrows are not saved to the dataset unless you turn on Include unchanged listings.EXPIREDis only produced once a run completes a full scan of the search, with no Max listings or Max pages cap cutting it short and noresumeFromRunId, and you turn on Include expired listings. A capped or resumed run cannot tell "gone" apart from "not reached yet", so it leaves the previous state untouched instead of guessing.REAPPEAREDonly happens for a listing that a previous run already markedEXPIRED. If Include expired listings has never been turned on, a listing that temporarily drops out of the results and comes back later is reported asUPDATEDorUNCHANGED, notREAPPEARED.
- Combining Incremental mode with
resumeFromRunIdis only supported to seed the very first incremental run from an existing full crawl. Once a baseline exists for a State key, the run fails with a clear message asking you to removeresumeFromRunIdor choose a different State key.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape, the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify > Settings > Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. If the picker is empty, you haven't authorized a connector yet.
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search (categories and locations) or url (paste a link). |
categories | array | none (prefill: ["restaurant"]) | Category URL slugs, for example restaurant, elektriker, zahnarzt. Required in search mode. |
locations | array | none (prefill: ["wien"]) | Austrian location slugs, for example wien, salzburg, bregenz. Empty means Austria-wide. |
urls | array | none (prefill: one example URL) | Full Herold.at search URLs. Used only in url mode. |
verifiedOnly | boolean | false | Keep only listings flagged "Verifiziert" (post-filter, applies in both modes). |
ratedOnly | boolean | false | Keep only listings with at least one rating (post-filter). |
minRating | integer | none | 0 to 5, drop listings below this average rating (post-filter); 0 means off, values outside 1 to 5 are ignored. |
maxPages | integer | none (unlimited) | Result pages to walk per search. Leave empty to walk until the site's own end-of-results signal, or sooner once Max listings is reached. |
maxListings | integer | 20 | Total cap across all searches. 0 means unlimited, still bounded by Max pages. |
fetchDetails | boolean | false | Also fetch each listing's detail page for GPS, opening hours, payment methods, founding date and reviews. Multiplies request count about 30x per result page. |
resumeFromRunId | string | none | Previous run ID or dataset ID to continue a large walk across separate runs. |
incrementalMode | boolean | false | Recurring monitoring of the same search: classify every listing as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED. |
stateKey | string | none (auto-derived from the search scope) | Manually name the Incremental mode baseline. |
emitUnchanged | boolean | false | Also save UNCHANGED listings to the dataset. |
emitExpired | boolean | false | Also save an EXPIRED row for a previously tracked listing that no longer appears, once a run completes a full scan. |
proxy | object | none (prefill: Apify residential, country AT; this is also the runtime fallback when the field is left empty) | Connection settings. |
mcpConnectors | array | none | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | none | Notion connector only: page under which records are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. |
Output Example
Sample shape, values are illustrative placeholders, not from a live listing.
{"id": "00000","url": "https://www.herold.at/gelbe-seiten/wien/00000/sample-company/","name": "Sample Company","category": "restaurant","regionSlug": "wien","position": 1,"isVerified": true,"breadcrumb": ["Home", "Gelbe Seiten", "Restaurant", "Wien"],"streetAddress": "Sample Street 1","postalCode": "1010","addressLocality": "Wien","addressRegion": "Wien","addressCountry": "AT","latitude": 48.0000,"longitude": 16.0000,"telephone": "+43 1 0000000","email": "contact@example.com","website": "https://example.com","logoUrl": "https://images.herold.at/optimize?url=...&width=320","primaryImage": "https://images.herold.at/optimize?url=...&width=320","imageCount": 1,"foundingDate": "2020","branchCode": "00000","paymentAccepted": ["Cash", "Card"],"openingHours": [{ "day": "Monday", "opens": "09:00", "closes": "18:00" },{ "day": "Tuesday", "opens": "09:00", "closes": "18:00" }],"ratingValue": 4.8,"ratingCount": 42,"reviewCount": 12,"bestRating": 5,"worstRating": 1,"reviews": [{ "author": "Sample Reviewer", "body": "Sample review text.", "rating": 5, "datePublished": "2026-01-01" }],"description": "Sample seller description text appears here when fetchDetails is on.","scrapedAt": "2026-01-01T00:00:00.000Z"}
Plan Requirement
The default already uses the residential connection option with country set to AT, which gives the most stable routing into Austria; keep this setting when calling the actor via the API, since it is only a prefill, not a schema default. The actor automatically opens a new session and retries when a request is refused or comes back empty, a few attempts per page before it gives up. If every connection tier keeps failing, the run still finishes successfully with an empty dataset rather than an error; check the run log for next steps.
FAQ
How much does it cost?
You pay per listing returned. Turning on Fetch detail pages adds far more requests per page, so it also adds more cost per listing. The Pricing tab shows the current rates. Use Max listings and Max pages to cap the cost of any run.
Is it legal to scrape Herold.at?
This actor collects only publicly listed business directory data. You are responsible for how you use it: follow Herold.at's terms and the laws that apply to you, including any rules on using business contact details for outreach, and get legal advice if you plan commercial redistribution.
Can I get only new or changed listings on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated, reappeared and, if enabled, expired listings, and unchanged ones are not billed by default.
What is the difference between Resume and Incremental mode?
Resume (resumeFromRunId) continues one specific interrupted run so you don't pay to re-scrape what it already saved. Incremental mode instead monitors the same search across separate scheduled runs and reports only what changed since last time. They solve different problems and are normally used one at a time, see the "Resume and recurring updates" tip above for the exact rules on combining them.
Why did my run return zero listings for a city I know has businesses there?
Two common causes. First, not every location and category combination has its own page on Herold.at, some city and category pairs simply return no results. Leave Locations empty to search all of Austria, then filter the output by addressLocality. Second, a post-fetch filter such as Rated businesses only or Minimum average rating may be dropping every listing that was found, try running without those filters first to confirm.
Why did my run fail instead of returning an empty dataset?
A fully refused connection does not fail the run; it finishes successfully with an empty dataset and a log entry explaining why, so check the run log first. The run genuinely fails only in three cases: a connection setting that cannot be set up at all, a resumeFromRunId that cannot be read, or combining Incremental mode with resumeFromRunId on a search that already has saved state.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
π Want more leads data?
Pair this actor with these related scrapers from the same team:
| π Willhaben.at Scraper From $1/1K. Scrape Willhaben.at listings into clean JSON with 40+ structured fields... | π TrueLocal AU Directory Listings & Reviews Scraper Scrape TrueLocal.com.au business listings by keyword, location, or URL. Extract names... |
| π Yellow Pages NZ From $0.8/1K. Scrapes business listings from Yellow.co.nz (New Zealand Yellow Pages)... | π PagesJaunes FR From $0.8/1K. Scrapes business listings from PagesJaunes.fr (French Yellow Pages)... |
| π 2GIS From $1/1K. Extract business and place data from 2GIS.com at scale. Get names, addresses... | π BetaList Scraper Scrape BetaList.com startup profiles with founder and contact enrichment. Extract startup... |
π Browse all abotapi scrapers
π¬ Support & custom scrapers
- π Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- π οΈ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
- β Enjoying it? A quick review on the actor page helps other users find it.