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
14
Total users
1
Monthly active users
6 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:
Behaviour change: in URL mode, leaving urls untouched now uses one example of each supported shape (it used to scrape nothing); with the default Max listings of 20 only the first example is read, so raise Max listings to cover them all. Supported shapes:
| Shape | Example |
|---|---|
| Category + location | https://www.herold.at/gelbe-seiten/wien/restaurant/ |
| Austria-wide category | https://www.herold.at/gelbe-seiten/restaurant/ |
| Paginated page | https://www.herold.at/gelbe-seiten/wien/restaurant/seite/2/ |
| Region with umlaut | https://www.herold.at/gelbe-seiten/k%C3%A4rnten/restaurant/ |
| Sub-category | https://www.herold.at/gelbe-seiten/wien/bierlokale-pubs/ |
| Single company page (one record) | https://www.herold.at/gelbe-seiten/wien/4F7QT/kfc/ |
A-Z firm directory letter (follows its company links and its /seite/N/ pages, limited by Max pages and Max listings) | https://www.herold.at/gelbe-seiten/firmen-az/a/ |
http:// and bare herold.at links are normalised to https://www.herold.at. ?seite=N links are read from page N (via /seite/N/); herold.at itself ignores the query. category is empty (null) for single company pages and A-Z letter pages, because their URL carries no category. Category index pages (/branchen-az/) list no businesses and are skipped with a warning. Paths that do not exist on the site (for example a region without a category) return a not-found page and yield no rows; a company link whose page is gone or cannot be read is skipped with a warning and not billed. Search mode keeps umlauts in names (KΓ€rnten, lower-cased).
URL mode, two category links:
{"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. - What counts as a change. A listing is
UPDATEDwhen a compared field changed;changedFieldsnames them.scrapedAt,position,logoUrl,primaryImage,imageCountand the order ofreviewsare never compared (they stay in the output). Use Ignore fields when detecting changes (incremental mode only) (ignoreFieldsForChanges) to exclude more, for examplereviewCountor the nestedreviews.datePublished. Changing this list never produces a wave ofUPDATEDrows: the stored baseline is re-compared with the current list on every run. EXPIREDis only reported after a complete scan. A run that hit Max listings or Max pages, started from a URL beyond page 1 (/seite/N/), or usedresumeFromRunIdkeeps the previous state untouched and reports nothing as expired.
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 | one example per supported URL shape | 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 (hard cap 1000) | Result pages to walk per search or URL. Leave empty to walk until the site's own end-of-results signal, a hard cap of 1000 pages, or sooner once Max listings is reached. |
maxListings | integer | 20 | Total cap across all searches. Hard cap of 100000 per run; 0 means that cap, 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. |
maxReviews | integer | 20 | With fetchDetails on, keeps at most this many reviews per listing (maximum 100, 0 = none); reviews are part of the normal result row and add no extra charge. |
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. |
ignoreFieldsForChanges | array | [] | Incremental mode only: field names (nested like reviews.datePublished) that never count as a change. |
proxy | object | none (prefill: Apify residential, country AT; this is also the runtime fallback when the field is left empty; datacenter also works) | 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 views
The dataset has four views: Listings (search-result fields), Detail (GPS, opening hours, payment methods, founding date, description), Reviews (one row per review, with the listing id, name and URL; the number of reviews per listing is set by maxReviews) and Changes (Incremental mode: changeType, changedFields, first and last seen). For users coming from other Herold.at scrapers, companyName, companyDetailUrl, companyDescription, companyAddress and companyPhone correspond to name, url, description, streetAddress with postalCode and addressLocality, and telephone; no extra fields are added, so existing Incremental baselines are not affected.
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
No paid proxy is required. In testing, the plain Apify datacenter pool read every Herold.at page type this actor uses (search pages, paginated pages, company pages), with no blocks observed. The prefill is still residential with country AT, which gives the most stable routing into Austria; the proxy group is your cost and your choice, so switch to datacenter in the Proxy configuration field if you prefer lower cost. Apify free plans do not include residential proxies: if the chosen connection is unavailable, the run logs "The selected connection is unavailable to this run. Apify free plans do not include residential proxies. Continuing on a backup connection; some pages may still be unavailable." and carries on over the account's default pool, then notes "Served over the backup connection (the default connection was unavailable)." Each listing is given a fixed time budget per attempt and retried on a fresh session.
If nothing can be read, the run says why instead of returning a silent empty dataset: "The proxy connection was refused for this account, so no page could be read. Your Apify plan does not include proxy access; a paid plan is required", or "No results: residential proxies are unavailable on this run (Apify free plans do not include them), and the backup connection could not load the requested Herold pages", or "Could not load any results page (the requests failed), so nothing was collected. This is a connection problem, not an empty search. Please try again later." A page that Herold.at itself reports as not found (for example a location and category pair with no page) is treated as an empty result, not a connection error.
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 (a start fee plus a per-result fee); reviews, detail fields and the changes view add no extra charge. 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 return a silent empty dataset: the run log states the reason (see Plan Requirement). 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:
| π TrueLocal AU Directory Listings & Reviews Scraper Scrape TrueLocal.com.au business listings by keyword, location, or URL. Extract names... | π Yellow Pages AU From $1/1K. Scrape business listings from Yellow Pages Australia by type and location... |
| π PagesJaunes FR From $0.8/1K. Scrapes business listings from PagesJaunes.fr (French Yellow Pages)... | π Yellow Pages NZ From $0.8/1K. Scrapes business listings from Yellow.co.nz (New Zealand Yellow Pages)... |
| π 2GIS From $1/1K. Extract business and place data from 2GIS.com at scale. Get names, addresses... | π Local.ch From $1/1K. Pull structured company data from local.ch, including name, address, GPS... |
π Browse all abotapi scrapers
π¬ Support
- π 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 contact@abotapi.com.
- β Enjoying it? A quick review on the actor page helps other users find it.