# 118000.fr Scraper — French Business & Phone Directory Leads (`worktech/118000-fr-scraper`) Actor

Scrape French business leads from 118000.fr: name, phone (+33), address, postal code, city and category. Search by trade and city — a fast PagesJaunes alternative. Pay per result. Export JSON, CSV or Excel.

- **URL**: https://apify.com/worktech/118000-fr-scraper.md
- **Developed by:** [Per Schondell](https://apify.com/worktech) (community)
- **Categories:** Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 business records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## 118000.fr Scraper — French Business & Phone Directory Leads

Extract **French business leads from 118000.fr** — business name, phone number in +33 format, street address, postal code, city and category — with no API key, no login, and no coding. This is the **only Apify actor for 118000.fr** and a **fast PagesJaunes alternative for French lead generation**: 118000.fr covers the same French market but is scrapable with plain HTTP, so runs are quick and cheap.

Type a trade and a city, press Run, and export your lead list to **JSON, CSV, or Excel**.

**Business listings only.** 118000.fr also lists private individuals (*particuliers*). This scraper deliberately excludes them — it collects professional/business records only, and individual white-pages entries are filtered out and never billed.

### What can you do with it?

- **Find plumbers in Lyon with phone numbers** — `searchTerms: ["plombier"]`, `locations: ["Lyon"]`
- **Get French business leads with address and postal code** — every record ships street, postal code, city, and geo coordinates when available
- **Build a French phone directory dataset by trade** — electricians, roofers, locksmiths, restaurants, garages: any 118000.fr category works
- **Scrape a PagesJaunes alternative without a bot wall** — same French SMB market, no hard CAPTCHA challenge
- **Generate cold-call and cold-mail lists for France** — phones are normalized to E.164 (`+33...`), ready for dialers and CRMs
- **Feed AI agents and pipelines** — structured output via API, webhooks, or the Apify MCP server

### Pricing

**$1.5 per 1,000 business records** ($0.0015 per record, pay-per-event `business-record`). You are only charged for clean business rows actually delivered to your dataset — pages that are gone, blocked, or filtered as private individuals cost nothing.

| Scenario | Run cost |
|----------|----------|
| All plumbers in Lyon (~500 records) | ~$0.75 |
| 10 trades × 10 cities, capped at 200 each (~20,000 records) | ~$30 |

### How to scrape 118000.fr (step by step)

1. Click **Try for free** — you'll need a free Apify account.
2. Enter one or more **search terms** in French (e.g. `plombier`, `électricien`, `restaurant`).
3. Enter **locations** — major French cities are recognized by name (`Lyon`, `Marseille`); for smaller towns append the department code (`Lavaur 81`). Leave empty for a France-wide search.
4. Optionally set **Max results per search** to cap each trade × city combination.
5. Click **Start**, then open the **Dataset** tab and export as JSON, CSV, Excel, HTML, or XML — or fetch it via API.

Power users can skip search entirely and pass direct 118000.fr URLs via **startUrls** — listing pages (`https://www.118000.fr/v_lyon_69/c_plombier`) or single business pages (`https://www.118000.fr/e_C0071624359`).

#### How search terms are resolved (type normal French words)

118000.fr organizes businesses under its own official category names, which often differ from the everyday trade word — there is no "électricien" category; the real one is *électricité générale (entreprise)*. You don't need to know that: the scraper resolves your term automatically.

1. **Curated table** — the most-searched French trades map instantly to verified category slugs (no extra request).
2. **The site's own search** — any other term is resolved through 118000.fr's search, taking the clear-majority category of the results.
3. **Never a quiet zero, never a lost result** — if a term can't be resolved, if a resolved category doesn't exist for a location, or if a listing can't be fetched at all, the run logs a warning and writes an explicit failure entry (`UNRESOLVED_TERM`, `GONE_CATEGORY` or `LISTING_FETCH_FAILED`, with the term and attempted slug) into the run's `SUMMARY`, telling you what to try instead. One unreachable listing never cancels the rest of the run, and the `SUMMARY` always reports exactly how many records you were delivered.

**Supported category examples** (resolved and verified): plombier, électricien, boulangerie, coiffeur, serrurier, menuisier, maçon, garagiste, médecin, chauffagiste, couvreur, jardinier — plus anything 118000.fr's search recognizes: restaurant, avocat, notaire, dentiste, vétérinaire, pharmacie, opticien, fleuriste, taxi, déménageur, and hundreds more.

Tip: accents help for homonyms — "macon" alone matches the town Mâcon, so use "maçon" (the curated table handles this one for you either way).

#### Input

```json
{
  "searchTerms": ["plombier", "électricien"],
  "locations": ["Lyon", "Paris"],
  "maxResultsPerSearch": 200,
  "requestDelayMs": 500
}
```

#### Sample output (one record)

```json
{
  "name": "Les Bons Artisans",
  "phone": "+33185052857",
  "street": "12 Rue de la République",
  "postalCode": "75011",
  "city": "Paris",
  "address": "12 Rue de la République, 75011 Paris",
  "categories": ["plombier"],
  "website": null,
  "email": null,
  "latitude": 48.8631,
  "longitude": 2.3708,
  "sourceUrl": "https://www.118000.fr/e_C0071630314",
  "scrapedAt": "2026-08-15T12:00:00+00:00"
}
```

### Use it from code or AI agents

Run the actor and read results with the Apify API or client libraries:

```bash
curl -X POST "https://api.apify.com/v2/acts/worktech~118000-fr-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"searchTerms":["plombier"],"locations":["Lyon"],"maxResultsPerSearch":100}'
```

It also works with **n8n, Make, Zapier**, webhooks, and the **Apify MCP server**, so AI agents can discover and call it as a tool.

### Why this scraper?

- **The only 118000.fr actor on Apify** — purpose-built for this source, not a generic crawler pointed at it
- **Everyday French trade words just work** — "electricien" and "boulangerie" are resolved to the site's real categories via a verified mapping + 118000.fr's own search, instead of silently returning 0 results
- **Phones normalized to +33 E.164** — national `01 85 05 28 57` becomes `+33185052857`, ready for dialers, WhatsApp, and CRM import
- **Directory chrome filtered out** — the directory's own 118000 / premium 0892 numbers, tracking links, and ad domains are never mistaken for business data
- **Business-only by policy** — private individuals (*particuliers*) are detected and skipped, never delivered, never billed
- **No silent failures** — unknown cities, invalid start URLs, and blocked listing pages raise named errors with an actionable message instead of returning an empty dataset
- **Fair billing** — data is pushed to your dataset *before* the charge event fires; you can never pay for rows you didn't receive

### FAQ

**Do I need an API key or a 118000.fr account?**
No. The scraper reads the public directory pages — the same data any visitor's browser sees.

**Can I export French business leads to CSV or Excel?**
Yes. Every run produces a dataset you can download as CSV, Excel, JSON, HTML, or XML from the Apify Console, or fetch via API.

**How many results can I get per search?**
Whatever 118000.fr serves for that trade + city — typically a few dozen to a few hundred per city, walked page by page. Use `maxResultsPerSearch` to cap it, or `0` for everything.

**Does it include private individuals (particuliers)?**
No, by design. Only professional/business listings are collected; white-pages entries for private individuals are filtered out.

**Is it legal to scrape 118000.fr?**
The actor collects publicly available business contact data. French business contact details are professional data, but whether scraping fits your use case (especially outreach under GDPR/CNIL rules) depends on your jurisdiction and purpose — when in doubt, consult a lawyer.

**My town isn't recognized — what do I do?**
Append the French department code to the location (`"Lavaur 81"`, `"Bastia 2B"`), or paste the 118000.fr listing URL for your town into `startUrls`.

**How complete are the phone numbers?**
Around 80% of records overall, varying by category — plumbers are near 100%, hairdressers around 85%. Records without a published phone still ship name, address, and category.

**Are email addresses and websites included?**
Emails: no — 118000.fr does not expose business email addresses, so the `email` field is always `null` (kept in the output for schema stability). Websites: only when a business publishes one on its page, which is rare on this source.

**What happens if I type a trade the site doesn't know?**
The run doesn't silently return nothing: you get a log warning and an explicit `UNRESOLVED_TERM` (or `GONE_CATEGORY`) entry in the run's `SUMMARY` with the term, the attempted slug, and a hint (try the accented/official trade word, a more specific term, or a direct startUrl).

### Limitations

- French businesses only — 118000.fr covers France (including Corsica; overseas departments as listed on the site).
- Phone coverage is ~80% and category-dependent (plombier ~100%, coiffeur ~85%); records without a phone are still delivered with name, address, and category.
- Email is never populated — 118000.fr does not expose email addresses. Websites are rare.
- No SIRET/SIREN numbers — 118000.fr does not publish company registration numbers.
- Very large France-wide crawls (no location, no cap) can take a while; prefer per-city searches or set `maxResultsPerSearch`.

### Status

**v0.2** — automatic term→category resolution (curated table + site search) with explicit `UNRESOLVED_TERM` / `GONE_CATEGORY` failure reporting; search by trade + city, direct URLs, pay-per-event billing, business-only filtering. 87 unit tests passing against captured 118000.fr fixtures, plus a 17-check in-image pre-push gate (`gate.py`).

# Actor input Schema

## `searchTerms` (type: `array`):

Business categories to search for, in French (e.g. plombier, électricien, restaurant). Combined with every location below.

## `locations` (type: `array`):

French cities (e.g. Lyon, Paris, Marseille). Major cities are recognized by name; for smaller towns append the department code, e.g. "Lavaur 81". Leave empty for a France-wide search.

## `startUrls` (type: `array`):

Direct 118000.fr listing URLs (https://www.118000.fr/v\_lyon\_69/c\_plombier) or business detail URLs (https://www.118000.fr/e\_C...). Used instead of / in addition to search terms.

## `maxResultsPerSearch` (type: `integer`):

Cap on business records per search term + location combination. 0 = unlimited (all result pages).

## `requestDelayMs` (type: `integer`):

Politeness delay between listing pages and between detail batches.

## `proxyConfiguration` (type: `object`):

Proxy settings for platform runs. Defaults to Apify automatic proxy.

## Actor input object example

```json
{
  "searchTerms": [
    "plombier"
  ],
  "locations": [
    "Lyon"
  ],
  "maxResultsPerSearch": 0,
  "requestDelayMs": 500,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `businessRecords` (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 = {
    "searchTerms": [
        "plombier"
    ],
    "locations": [
        "Lyon"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("worktech/118000-fr-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 = {
    "searchTerms": ["plombier"],
    "locations": ["Lyon"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("worktech/118000-fr-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 '{
  "searchTerms": [
    "plombier"
  ],
  "locations": [
    "Lyon"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call worktech/118000-fr-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,worktech/118000-fr-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/7tEGvV4Yjqnlq5zTS/builds/XxwRTZVYtG3qDO6Je/openapi.json
