Herold.at Scraper - Austrian Businesses, Contacts & Reviews avatar

Herold.at Scraper - Austrian Businesses, Contacts & Reviews

Pricing

from $0.80 / 1,000 results

Go to Apify Store
Herold.at Scraper - Austrian Businesses, Contacts & Reviews

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

Abot API

Maintained by Community

Actor stats

0

Bookmarked

14

Total users

1

Monthly active users

6 days ago

Last modified

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.

FieldExample
id"00000" (Herold.at listing ID)
url"https://www.herold.at/gelbe-seiten/wien/00000/sample-company/"
name"Sample Company"
category"restaurant"
regionSlug"wien"
isVerifiedtrue ("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"
ratingValue4.8 (average rating, 1 to 5)
ratingCount42
branchCode"00000"
latitude48.0000 (requires Fetch detail pages)
longitude16.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

  1. Pick a mode: search (categories and locations) or url (paste a prepared Herold.at search link).
  2. 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.
  3. 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.
  4. 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:

ShapeExample
Category + locationhttps://www.herold.at/gelbe-seiten/wien/restaurant/
Austria-wide categoryhttps://www.herold.at/gelbe-seiten/restaurant/
Paginated pagehttps://www.herold.at/gelbe-seiten/wien/restaurant/seite/2/
Region with umlauthttps://www.herold.at/gelbe-seiten/k%C3%A4rnten/restaurant/
Sub-categoryhttps://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 ApifyClient
client = 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 listing id already 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 classified NEW, UPDATED (with changedFields), UNCHANGED, REAPPEARED or EXPIRED.
    • UNCHANGED rows are not saved to the dataset unless you turn on Include unchanged listings.
    • EXPIRED is only produced once a run completes a full scan of the search, with no Max listings or Max pages cap cutting it short and no resumeFromRunId, 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.
    • REAPPEARED only happens for a listing that a previous run already marked EXPIRED. If Include expired listings has never been turned on, a listing that temporarily drops out of the results and comes back later is reported as UPDATED or UNCHANGED, not REAPPEARED.
  • Combining Incremental mode with resumeFromRunId is 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 remove resumeFromRunId or choose a different State key.
  • What counts as a change. A listing is UPDATED when a compared field changed; changedFields names them. scrapedAt, position, logoUrl, primaryImage, imageCount and the order of reviews are never compared (they stay in the output). Use Ignore fields when detecting changes (incremental mode only) (ignoreFieldsForChanges) to exclude more, for example reviewCount or the nested reviews.datePublished. Changing this list never produces a wave of UPDATED rows: the stored baseline is re-compared with the current list on every run.
  • EXPIRED is 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 used resumeFromRunId keeps 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.

  1. Authorize a connector once under Apify > Settings > Integrations (Notion, Linear, Airtable, or Apify).
  2. Select it in the "Pipe results into your apps" input field. If the picker is empty, you haven't authorized a connector yet.
  3. For Notion, also set notionParentPageUrl to 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

ParameterTypeDefaultDescription
modestringsearchsearch (categories and locations) or url (paste a link).
categoriesarraynone (prefill: ["restaurant"])Category URL slugs, for example restaurant, elektriker, zahnarzt. Required in search mode.
locationsarraynone (prefill: ["wien"])Austrian location slugs, for example wien, salzburg, bregenz. Empty means Austria-wide.
urlsarrayone example per supported URL shapeFull Herold.at search URLs. Used only in url mode.
verifiedOnlybooleanfalseKeep only listings flagged "Verifiziert" (post-filter, applies in both modes).
ratedOnlybooleanfalseKeep only listings with at least one rating (post-filter).
minRatingintegernone0 to 5, drop listings below this average rating (post-filter); 0 means off, values outside 1 to 5 are ignored.
maxPagesintegernone (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.
maxListingsinteger20Total cap across all searches. Hard cap of 100000 per run; 0 means that cap, still bounded by Max pages.
fetchDetailsbooleanfalseAlso fetch each listing's detail page for GPS, opening hours, payment methods, founding date and reviews. Multiplies request count about 30x per result page.
maxReviewsinteger20With 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.
resumeFromRunIdstringnonePrevious run ID or dataset ID to continue a large walk across separate runs.
incrementalModebooleanfalseRecurring monitoring of the same search: classify every listing as NEW, UPDATED, UNCHANGED, REAPPEARED or EXPIRED.
stateKeystringnone (auto-derived from the search scope)Manually name the Incremental mode baseline.
emitUnchangedbooleanfalseAlso save UNCHANGED listings to the dataset.
emitExpiredbooleanfalseAlso save an EXPIRED row for a previously tracked listing that no longer appears, once a run completes a full scan.
ignoreFieldsForChangesarray[]Incremental mode only: field names (nested like reviews.datePublished) that never count as a change.
proxyobjectnone (prefill: Apify residential, country AT; this is also the runtime fallback when the field is left empty; datacenter also works)Connection settings.
mcpConnectorsarraynoneOptional: send a summary of each record to apps you authorized under Integrations.
notionParentPageUrlstringnoneNotion connector only: page under which records are created.
maxNotifyListingsinteger50Cap 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.

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.