# PagesJaunes Leads, Reviews & Local SEO Scraper (`thescrapelab/pagesjaunes-leads-reviews-scraper`) Actor

Scrape PagesJaunes business leads across France with phone numbers, websites, addresses, ratings, reviews, opening hours, and SIRET/SIREN data.

- **URL**: https://apify.com/thescrapelab/pagesjaunes-leads-reviews-scraper.md
- **Developed by:** [Inus Grobler](https://apify.com/thescrapelab) (community)
- **Categories:** Lead generation, SEO tools, Marketing
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 business records

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## PagesJaunes Leads, Reviews & Local SEO Scraper

Scrape PagesJaunes business listings and build structured French B2B lead lists with phone numbers, websites, addresses, ratings, reviews, opening hours, and SIRET/SIREN data.

Enter a business type, a location in France, and the number of results you need. The Actor searches PagesJaunes, removes duplicates, and returns ready-to-download lead data. Fast search-card extraction is the default; full public profile enrichment is optional. No PagesJaunes account or third-party data API is required.

### Why use this PagesJaunes scraper?

- Build targeted French business lead lists by profession and location
- Find public phone numbers and company websites without manual copy-and-paste
- Compare local competitors using ratings, review counts, categories, and services
- Collect SIRET, SIREN, NAF code, and legal-form data when PagesJaunes displays it
- Export clean results to CSV, Excel, JSON, XML, RSS, or JSONL
- Optionally look for public business email addresses on listed company websites

### PagesJaunes data you can collect

- Business name, description, category, and PagesJaunes URL
- Address, postal code, city, coordinates, phone, and website
- SIRET, SIREN, NAF code, and legal form when displayed
- Opening hours and visible business status
- Rating, review count, and public review snippets shown on the profile
- Public business email addresses when optional website enrichment is enabled

### Input: how to scrape PagesJaunes business leads

For a normal run, fill in only three fields:

1. **What type of business?** — for example, `plombier` or `dentiste`.
2. **Where in France?** — for example, `Paris 75000` or `Lyon 69000`.
3. **How many businesses?** — the maximum number of rows you want.

```json
{
  "query": "plombier",
  "location": "Paris 75000",
  "maxItems": 25
}
```

That is enough for a fast, economical lead list. Add `"includeDetails": true` when you need the richer profile fields. Adding a postal code gives the clearest location match.

| Field | Description | Default |
| --- | --- | --- |
| `query` | Profession, service, or business category | `plombier` |
| `location` | French city, area, or postal code | `Paris 75000` |
| `maxItems` | Maximum unique businesses returned | `1` |
| `includeDetails` | Visit every profile for websites, legal identifiers, hours, ratings, and reviews | `false` |
| `includeReviewSnippets` | Include reviews when full details are enabled | `true` |
| `enrichEmailsFromWebsite` | Visit the listed public business website to find email addresses; automatically enables full details | `false` |

The **Advanced options** section supports direct PagesJaunes URLs, multiple searches, page limits, review limits, and browser tuning. Most users can leave it unchanged. Direct URLs or multiple searches replace the simple search fields rather than adding unexpected extra results.

Residential proxy access is preconfigured because PagesJaunes may present automated-access challenges. Start with fast mode and a small result count, check the output, and enable full details only when the additional fields are worth the extra runtime and proxy traffic.

The Actor is tuned for **1,024 MB RAM** and `maxConcurrency: 1`. That is the smallest reliable Chromium configuration and the fastest, lowest-cost concurrency found in cloud stress tests. Higher concurrency can trigger source throttling and cost more; use 2 GB only if you deliberately raise concurrency to `3` after testing your own workload. Fast mode commonly completes small searches in seconds. Full-detail mode opens one additional page per business and therefore takes materially longer. The default 15-minute timeout is a safety ceiling—successful runs stop as soon as collection finishes. For unusually large inputs, raise the run timeout explicitly and scale in measured batches.

### PagesJaunes scraper output

The default dataset contains one row per business. Fast mode fills the fields available on the search card and leaves unavailable enrichment fields empty. With **Collect full business details** enabled, a row can look like this:

```json
{
  "businessId": "123-plomberie-durand",
  "name": "Plomberie Durand",
  "profileUrl": "https://www.pagesjaunes.fr/pros/123-plomberie-durand",
  "sourceUrl": "https://www.pagesjaunes.fr/annuaire/paris-75000/plombier",
  "searchQuery": "plombier",
  "locationQuery": "Paris 75000",
  "address": "10 rue de Paris, 75001 Paris",
  "postalCode": "75001",
  "city": "Paris",
  "phone": "01 23 45 67 89",
  "website": "https://example.fr/",
  "siret": "12345678901234",
  "rating": 4.8,
  "reviewCount": 27,
  "reviewSnippets": [
    {
      "author": "Alice",
      "rating": 5,
      "text": "Intervention rapide et soignée.",
      "date": "2026-08-01"
    }
  ],
  "scrapedAt": "2026-09-10T12:00:00.000Z",
  "completenessScore": 90
}
```

The most useful columns are:

| Column | Meaning |
| --- | --- |
| `name` | Business name |
| `phone`, `website`, `email` | Available public contact details |
| `address`, `city`, `postalCode` | Business location |
| `rating`, `reviewCount` | PagesJaunes reputation summary |
| `siret`, `siren`, `nafCode` | French business identifiers when displayed |
| `profileUrl` | Source PagesJaunes business page |
| `completenessScore` | Percentage of key fields found, from 0 to 100 |

The Dataset tab starts with a clean overview of the main lead fields. You can preview the rows or download JSON, CSV, Excel, XML, RSS, or JSONL. The Actor output also contains direct links to JSON results, CSV results, and `RUN_SUMMARY` diagnostics.

### Common use cases

- **B2B lead generation:** find plumbers, dentists, restaurants, agencies, tradespeople, and other businesses in a French city or postal area.
- **Local SEO research:** compare categories, reviews, ratings, services, and listing completeness across local competitors.
- **Sales prospecting:** export public business contact details for qualification and CRM research.
- **Market analysis:** measure the number and profile of businesses serving a location or category.
- **Directory monitoring:** create timestamped snapshots of opening hours, ratings, review counts, and business details.

### Pricing and usage costs

The Actor charges **$0.003 per business record** ($3 per 1,000 results), plus the Apify platform resources and French Residential Proxy traffic consumed by the run. You can set a maximum charge before starting a run; collection stops gracefully when that limit is reached.

Fast mode uses only search-result pages and is the economical default. Full details add one profile request per business, while email enrichment can add several bounded requests to the listed public website. Start with a small `maxItems` value before scaling either enrichment option. Apify displays the final event and platform-usage charges on the run page.

### Use from Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
actor = client.actor("thescrapelab/pagesjaunes-leads-reviews-scraper")

run = actor.call(run_input={
    "query": "plombier",
    "location": "Paris 75000",
    "maxItems": 25,
    "includeDetails": True,
})

for business in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(business["name"], business.get("phone"), business["profileUrl"])
```

### Run statuses

- `SUCCEEDED`: requested businesses were collected without request or enrichment failures.
- `PARTIAL`: useful records were returned, but one or more requests or optional enrichments failed.
- `NO_RESULTS`: PagesJaunes was reached successfully but the search returned no usable listings.
- `LIMIT_REACHED`: useful records were returned and collection stopped at your maximum charge.
- `BLOCKED`: the source continued to show a security challenge after bounded session rotation.
- `FAILED`: no usable result could be produced because of a non-blocking runtime error.

### FAQ

#### Do I need a PagesJaunes API or account?

No. The Actor reads information displayed on public PagesJaunes search and business-profile pages.

#### Can I search anywhere in France?

Yes. Enter a French city, area, or postal code. Combining the city and postal code, such as `Lyon 69000`, normally gives the clearest location match.

#### Does every result include an email address?

No. PagesJaunes does not consistently display email addresses. Enable **Look for business emails** to check the public company website. This automatically enables full profile details, but an email is returned only when one is publicly available.

#### Why did I receive fewer results than requested?

The source may have fewer matching businesses, duplicate listings, unavailable profiles, or a limited number of result pages. Increase **Maximum search pages** in Advanced options when more PagesJaunes pages are available.

### Support

If a run returns unexpected results, first check that the business term is suitable for a French directory and add a postal code to the location. When reporting a persistent problem through the Actor's Issues tab, include the Apify run ID and a non-sensitive example of the input so the run can be investigated.

### Responsible use and limitations

This independent Actor collects only information displayed on public business-search and profile pages. It does not access private accounts, personal reverse lookup, contact forms, dedicated review endpoints, or hidden/private data. Email enrichment is limited to public business websites and never submits forms.

Source markup and availability can change. Use reasonable limits, comply with applicable terms and laws, and do not use exported contact data for unlawful or unsolicited activity. This Actor is not affiliated with PagesJaunes or Solocal.

# Actor input Schema

## `query` (type: `string`):

A profession, service, or category, for example: plombier, dentiste, restaurant, or agence web.

## `location` (type: `string`):

A city, area, or postal code. City plus postal code gives the clearest match, for example: Lyon 69000.

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

The maximum number of unique business rows saved to your results.

## `includeDetails` (type: `boolean`):

Visit every profile to collect websites, legal details, opening hours, ratings, and reviews. Detailed runs are slower and use more residential-proxy traffic.

## `includeReviewSnippets` (type: `boolean`):

Save visible review snippets when full business details are enabled. This option has no effect in fast mode.

## `enrichEmailsFromWebsite` (type: `boolean`):

Check the business's public website for email addresses. Enabling this automatically enables full details and therefore makes runs slower and uses more proxy traffic.

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

Optional direct PagesJaunes search or business-profile URLs. When supplied, these replace the simple search above.

## `searches` (type: `array`):

Run several business-and-location searches together. When supplied, these replace both the simple search and direct URLs.

## `maxPagesPerSearch` (type: `integer`):

Stops each search after this many result pages, even when more results are available.

## `maxReviewSnippetsPerBusiness` (type: `integer`):

Maximum visible review snippets saved for each business.

## `maxWebsitePagesPerBusiness` (type: `integer`):

Maximum homepage, contact, or about pages checked when email lookup is enabled.

## `maxConcurrency` (type: `integer`):

Leave at 1 for the best tested speed and cost at 1 GB RAM. Higher values can trigger source throttling; use 3 only with 2 GB RAM and your own measurements.

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

French Residential Proxy is preconfigured for reliable PagesJaunes access. Change this only if you have your own compatible proxy.

## Actor input object example

```json
{
  "query": "plombier",
  "location": "Paris 75000",
  "maxItems": 1,
  "includeDetails": false,
  "includeReviewSnippets": true,
  "enrichEmailsFromWebsite": false,
  "startUrls": [],
  "maxPagesPerSearch": 3,
  "maxReviewSnippetsPerBusiness": 3,
  "maxWebsitePagesPerBusiness": 3,
  "maxConcurrency": 1,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "FR"
  }
}
```

# Actor output Schema

## `businesses` (type: `string`):

One structured row per business, suitable for apps and integrations.

## `businessesCsv` (type: `string`):

Spreadsheet-friendly business results for Excel, Google Sheets, or a CRM.

## `runSummary` (type: `string`):

Status, result counts, warnings, retries, and access diagnostics for this run.

# 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 = {
    "query": "plombier",
    "location": "Paris 75000"
};

// Run the Actor and wait for it to finish
const run = await client.actor("thescrapelab/pagesjaunes-leads-reviews-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 = {
    "query": "plombier",
    "location": "Paris 75000",
}

# Run the Actor and wait for it to finish
run = client.actor("thescrapelab/pagesjaunes-leads-reviews-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 '{
  "query": "plombier",
  "location": "Paris 75000"
}' |
apify call thescrapelab/pagesjaunes-leads-reviews-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,thescrapelab/pagesjaunes-leads-reviews-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/bF0dFnMYSkEfRhzLe/builds/pQgMxcEWnR8VvOAVU/openapi.json
