# Local.ch Leads Scraper (`parsebird/localch-leads-scraper`) Actor

Extract business leads from Local.ch search results: names, addresses, phone numbers, websites, social profiles, ratings, opening hours, and categories.

- **URL**: https://apify.com/parsebird/localch-leads-scraper.md
- **Developed by:** [ParseBird](https://apify.com/parsebird) (community)
- **Categories:** Lead generation, Automation, Integrations
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 1 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.70 / 1,000 leads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### Local.ch Leads Scraper

Scrape business leads from [Local.ch](https://www.local.ch/) — Switzerland's largest business directory. Point Local.ch Leads Scraper at any search results page and get structured data back for every business: name, address, phone, website, social profiles, ratings, opening hours, categories, and the site's own attribute tags.

<table><tr>
<td style="border-left:4px solid #1C1917;padding:12px 16px;font-weight:600">
Reads Local.ch's own per-business data directly, so every lead comes back with real contact details, structured opening hours for all seven days, and category-grouped attribute tags — not just what's visible on the search results card.
</td>
</tr></table>

##### Copy to your AI assistant

Copy this block into ChatGPT, Claude, Cursor, or any LLM to start using this Actor.

```
Local.ch Leads Scraper (parsebird/localch-leads-scraper) — Scrapes business leads from Local.ch search results pages. Input: {"startUrl": "https://www.local.ch/en/q/zurich/general-internal-medicine", "maxItems": 100}. Key inputs: startUrl (string, required — a local.ch search results URL with any filters already applied via local.ch's own filter UI), maxItems (integer, default 100, max number of businesses to scrape). Output per business: identity (id, title, subtitle, entryType, schemaOrgPlaceType), location (street, city, cantonCode, zipCode, country, latitude, longitude, poBoxCity, poBoxZipCode), contact (phone array, website, facebook, instagram, linkedin, twitter), categories (array), attributes (flat array plus attributesByGroup_<GroupName> fields per the site's own attribute groups), rating (averageRating, ratingCount, reviewCount, displayAverageRating, reviews), hours (openingHours as 7 daily text lines, openingHoursInfoLines, opensAt, opensAtType), media (images array), and metadata (isPremium, hasProducts, products, services, provider, language, lastModified, url). API: POST https://api.apify.com/v2/acts/parsebird~localch-leads-scraper/runs?token=YOUR_TOKEN. Get token: https://console.apify.com/account#/integrations
```

### What does Local.ch Leads Scraper do?

**Local.ch Leads Scraper** turns a Local.ch search results page into structured, spreadsheet-ready lead data. Give it a URL and it:

- 🔍 Accepts any Local.ch search results URL — a city + category page, a free-text search, or a search with filters, sorting, or booking parameters already applied
- 📇 Returns full contact details for every business: phone numbers, website, and Facebook/Instagram/LinkedIn/Twitter profiles, parsed out individually
- ⭐ Includes rating average, rating count, and review count for every lead
- 🕑 Structures opening hours into a readable line per day (`"MONDAY: 08:00-12:00, 13:00-16:30"` or `"SUNDAY: closed"`), plus any special holiday notices
- 🏷️ Surfaces the site's own attribute tags — languages spoken, payment methods, services offered, and more — both as a flat list and grouped by category (`attributesByGroup_Languages`, `attributesByGroup_Payment_methods`, ...)
- 📍 Includes latitude/longitude and full address for every lead, ready to drop on a map
- 📄 Paginates automatically — set `maxItems` and it keeps fetching result pages and business details until it has enough leads
- ⚡ No browser, no login — reads the same public business data local.ch itself renders, so it's fast and lightweight

Local.ch Leads Scraper reads Local.ch's own structured per-business data, so contact details, categories, and attributes match exactly what's shown on the business's local.ch page.

### What data can you extract from Local.ch?

| Field | Description |
|-------|-------------|
| `title` / `subtitle` | Business name and tagline |
| `street` / `city` / `cantonCode` / `zipCode` | Address, split into fields |
| `latitude` / `longitude` | Geographic coordinates |
| `phone` / `website` | Contact numbers and website URL |
| `facebook` / `instagram` / `linkedin` / `twitter` | Social profile URLs, when published |
| `categories` | List of categories the business is listed under |
| `attributes` / `attributesByGroup_*` | Site-published attribute tags, flat and grouped |
| `averageRating` / `ratingCount` / `reviewCount` | Rating summary |
| `openingHours` / `openingHoursInfoLines` | Daily hours and holiday/special notices |
| `images` | Photo and logo URLs |
| `isPremium` / `hasProducts` | Listing status signals |

That's 15 of 40+ output fields. See the [output example](#output-example) below for the complete record.

### How to scrape Local.ch leads with Local.ch Leads Scraper

1. Open [Local.ch Leads Scraper](https://apify.com/parsebird/localch-leads-scraper) on Apify
2. Go to [Local.ch](https://www.local.ch/), search a city and category (or a free-text query), and apply any filters, sorting, or booking parameters you want
3. Copy the resulting URL from your browser's address bar and paste it into **Start URL**
4. Set **Max items** to how many leads you need
5. Click **Start** and wait for the run to finish
6. Export your data as **JSON, CSV, or Excel** from the dataset tab, or pull it via the [Apify API](https://docs.apify.com/api/v2)

**Basic search:**

```json
{
    "startUrl": "https://www.local.ch/en/q/zurich/general-internal-medicine",
    "maxItems": 100
}
```

**Filtered category search:**

```json
{
    "startUrl": "https://www.local.ch/de/s/Mechanische%20Werkstatt%2C%20Deutsch?sorting=alphanum&filter_facet=attr_conversion_modifications%3Aaccessory",
    "maxItems": 200
}
```

**Restaurants with a specific attribute, in French:**

```json
{
    "startUrl": "https://www.local.ch/fr/s/Restaurant%20Basel?filter_facet=attr_services_offer%3Aaperitif",
    "maxItems": 50
}
```

### Output example

```json
{
  "attributes": ["Allemand", "Français", "Berne", "Administration fiscale", "Près des transports publics", "Dans le commerce", "En ligne", "Par téléphone"],
  "attributesByGroup_Canton": ["Berne"],
  "attributesByGroup_Langues": ["Allemand", "Français"],
  "averageRating": 1,
  "cantonCode": "BE",
  "categories": ["Administration", "Déclaration d'Impôts", "Service des impôts"],
  "city": "Bienne",
  "country": "CH",
  "entryType": "BUSINESS",
  "facebook": "https://www.facebook.com/Cantondeberne",
  "id": "HB_9l7mYVyIIk5I6yDaSYA",
  "latitude": 47.13294,
  "longitude": 7.244143,
  "openingHours": ["SATURDAY: closed", "SUNDAY: closed", "MONDAY: 08:00-12:00, 13:00-16:30"],
  "phone": ["+41316336001"],
  "rateable": true,
  "ratingCount": 1,
  "reviewCount": 0,
  "reviews": [],
  "schemaOrgPlaceType": "LocalBusiness",
  "street": "Bahnhofplatz 10",
  "title": "Intendance des impôts du canton de Berne, Région Jura bernois-Seeland",
  "url": "https://www.local.ch/fr/d/bienne/2502/administration/intendance-des-impots-du-canton-de-berne-region-jura-bernois-seeland-HB_9l7mYVyIIk5I6yDaSYA",
  "website": "http://www.taxme.ch",
  "zipCode": 2502
}
```

(Trimmed for brevity — the full row carries every column in the [data table](#what-data-can-you-extract-from-local-ch) above, including `subtitle`, `instagram`/`linkedin`/`twitter`, `images`, `openingHoursInfoLines`, `provider`, `products`, `services`, and every `attributesByGroup_*` field the business actually has.)

### Use cases

- **Lead generation** — Build a contact list of businesses in a city, canton, or category, complete with phone, website, and social profiles
- **Market research** — Compare category coverage, attributes, and ratings across a Swiss city or region
- **Sales prospecting** — Filter by attributes (payment methods, languages spoken, services offered) to target businesses that match your ideal customer profile
- **Directory and data enrichment** — Cross-reference your own business database against Local.ch's public listings
- **Competitive analysis** — Track how competitors in your category are rated and what attributes they advertise

### How much does it cost to scrape Local.ch?

Local.ch Leads Scraper uses [pay-per-event pricing](https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event) — you're charged per business lead saved to the dataset, not for compute time.

| Event | Price per event | Price per 1,000 |
|-------|-----------------|------------------|
| `lead-scraped` (Free plan) | $0.0015 | **$1.50** |
| `lead-scraped` (Bronze plan) | $0.0009 | **$0.90** |
| `lead-scraped` (Silver plan) | $0.0008 | **$0.80** |
| `lead-scraped` (Gold plan) | $0.0007 | **$0.70** |

**Cost examples (Gold plan):**

| Scenario | Leads | Cost |
|----------|-------|------|
| Quick category check (default `maxItems`) | 100 | $0.07 |
| Filtered category search | 200 | $0.14 |
| Large multi-city collection | 5,000 | $3.50 |

The [Apify Free plan](https://apify.com/pricing) includes $5/month in platform credits — enough for roughly 3,300 leads a month at the free-tier rate, no credit card required.

### Integrations and API access

Use Local.ch Leads Scraper programmatically via the [Apify API](https://docs.apify.com/api/v2), the [JavaScript client](https://docs.apify.com/api/client/js), or the [Python client](https://docs.apify.com/api/client/python).

**Python:**

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_API_TOKEN")

run = client.actor("parsebird/localch-leads-scraper").call(run_input={
    "startUrl": "https://www.local.ch/en/q/zurich/general-internal-medicine",
    "maxItems": 200,
})

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item.get("phone"), item.get("website"))
```

**JavaScript:**

```javascript
import { ApifyClient } from "apify-client";

const client = new ApifyClient({ token: "YOUR_API_TOKEN" });

const run = await client.actor("parsebird/localch-leads-scraper").call({
    startUrl: "https://www.local.ch/en/q/zurich/general-internal-medicine",
    maxItems: 200,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => console.log(item.title, item.phone, item.website));
```

You can also connect Local.ch Leads Scraper to [Google Sheets](https://apify.com/integrations/google-sheets), [Slack](https://apify.com/integrations/slack), [Zapier](https://apify.com/integrations/zapier), [Make](https://apify.com/integrations/make), and other CRM tools via [Apify integrations](https://apify.com/integrations). Schedule runs with [Apify Schedules](https://docs.apify.com/platform/schedules) to refresh a lead list on a recurring basis.

### Is it legal to scrape Local.ch?

Scraping publicly available data is generally considered legal, based on the [2022 US appeals court ruling](https://blog.apify.com/is-web-scraping-legal/) in *hiQ Labs v. LinkedIn*. This Actor only reads business data that's already publicly visible on Local.ch search and listing pages — it does not log in or access any non-public data.

Always review [Local.ch's Terms of Use](https://www.local.ch/en/terms-of-use) and comply with applicable laws in your jurisdiction, including Swiss data protection rules if you plan to use the leads for outreach. For guidance, see [Apify's guide to web scraping legality](https://blog.apify.com/is-web-scraping-legal/).

### FAQ

**What URL formats does `startUrl` accept?**
Any public Local.ch search results page: a `/q/{city}/{category}` page, a `/s/{query}` free-text search, with or without `filter_facet`, `sorting`, or `bookingFilters.*` query parameters. Apply filters on local.ch itself, then paste the resulting URL — the Actor scrapes whatever results that URL produces, including pagination beyond the first page.

**Does `maxItems` include only businesses, or also ads and suggestions?**
Only actual business listings (`entryType: "BUSINESS"`) count toward `maxItems` and are charged.

**Why is `reviews` usually an empty array even when `reviewCount` is greater than 0?**
Local.ch's business pages expose the rating summary (`averageRating`, `ratingCount`, `reviewCount`) directly, but individual written reviews require a separate paginated request the site only loads on demand — so `reviews` reflects what's included on the business's own page, which is often empty even for rated businesses. This is a genuine gap in what's publicly embedded, not a scraping error.

**Why are some fields `null` or empty?**
Local.ch doesn't publish every field for every business — for example, `poBoxCity` is `null` when a business has no separate PO box, and social fields like `instagram` are `null` when the business hasn't linked that profile. `attributesByGroup_*` fields only appear for the attribute groups a specific business actually has, so different records can have different sets of these columns.

**Can I schedule recurring runs?**
Yes. Use [Apify's scheduling feature](https://docs.apify.com/platform/schedules) to re-run a saved search daily, weekly, or at any interval to keep a lead list current.

**Can I use this with my AI assistant or MCP server?**
Yes. Copy the AI assistant block from the top of this page into ChatGPT, Claude, or Cursor, or connect it to any agent framework through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp).

**Something isn't working. How do I get help?**
Open an issue in the [Issues tab](https://apify.com/parsebird/localch-leads-scraper/issues) on the Actor page. Include your input configuration and any error messages.

# Actor input Schema

## `startUrl` (type: `string`):

A Local.ch search results page URL, with any filters you want already applied. Apply filters on local.ch first, then paste the resulting URL here.

## `maxItems` (type: `integer`):

Maximum number of businesses to scrape.

## Actor input object example

```json
{
  "startUrl": "https://www.local.ch/en/q/zurich/general-internal-medicine",
  "maxItems": 20
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "startUrl": "https://www.local.ch/en/q/zurich/general-internal-medicine",
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("parsebird/localch-leads-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "startUrl": "https://www.local.ch/en/q/zurich/general-internal-medicine",
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("parsebird/localch-leads-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "startUrl": "https://www.local.ch/en/q/zurich/general-internal-medicine",
  "maxItems": 20
}' |
apify call parsebird/localch-leads-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,parsebird/localch-leads-scraper"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/aNTWwgwNH5bAlI1Tf/builds/0tGb2QIJr83nIcXJO/openapi.json
