# Paginas Amarillas Listings Scraper · Phones, hours · $4/1K (`mlg14/paginasamarillas-scraper`) Actor

Find Spanish businesses on Paginas Amarillas for lead generation, local market research and directory building. Search by term and city or URL; returns names, phones, addresses, websites, hours, ratings and coordinates. $4/1K listings.

- **URL**: https://apify.com/mlg14/paginasamarillas-scraper.md
- **Developed by:** [MLG Data](https://apify.com/mlg14) (community)
- **Categories:** Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$4.00 / 1,000 results

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/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
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.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## 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.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Paginas Amarillas Scraper

Scrape Spanish business listings from paginasamarillas.es by category, keyword, city, or a saved directory URL. Export paginasamarillas.es data to JSON, CSV, or Excel-compatible files, and use the structured dataset as a paginasamarillas.es API alternative for lead research, local market analysis, and directory monitoring.

The actor returns one flat row per unique listing. Search pages provide business names, public phone numbers, addresses, categories, descriptions, websites, profile links, and paid-placement signals; optional profile requests add fields such as opening hours, rating, review count, coordinates, email, logo, and social links when the profile publishes them.

### What data can you extract from Paginas Amarillas?

The directory publishes different fields for different businesses. Search-card data is collected first. When `scrapeDetails` is enabled, the actor opens the associated public business profile to look for additional details. Empty values mean the page did not expose that field in the returned markup; they do not indicate that the business has no such information.

| Field | Description | Example |
| --- | --- | --- |
| `listingId` | Stable identifier derived from the profile URL. | `195495346` |
| `slug` | Business profile slug. | `la-daniela-cuchilleros` |
| `name` | Display name of the business. | `La Daniela Cuchilleros` |
| `paginasAmarillasUrl` | Public directory profile URL. | `https://www.paginasamarillas.es/f/madrid/la-daniela-cuchilleros_195495346_000000002.html` |
| `isPremium` | Whether the directory marks the result as a paid placement. | `true` |
| `phone` | First public phone number found. | `913662018` |
| `phones` | All phone numbers found on the listing and profile. | `[` `"913662018"` `]` |
| `fax` | Public fax number, when present. | `null` |
| `email` | Public email address, when present. | `null` |
| `website` | External business website. | `http://www.tabernadeladaniela.com` |
| `social` | Social profile URLs found on the page; directory-owned links can also appear. | `[` `"https://facebook.com/LADANIELACUCHILLEROS"` `]` |
| `address` | Formatted address as shown on the directory. | `Calle de los Cuchilleros, 9 , 28005 , Madrid` |
| `street` | Street name and number. | `Calle de los Cuchilleros, 9` |
| `postalCode` | Postal code. | `28005` |
| `city` | Locality shown in the address. | `Madrid` |
| `region` | Province or region, when present. | `Madrid` |
| `country` | Country associated with these Spain-only results. | `Spain` |
| `latitude` | Latitude from profile map data. | `40.414341585` |
| `longitude` | Longitude from profile map data. | `-3.70799292` |
| `category` | Main category shown on the search card. | `Cocina madrileña Cocina castellana | Restaurante` |
| `categories` | List of directory categories associated with the result. | `[` `"Cocina madrileña Cocina castellana | Restaurante"` `]` |
| `rating` | Published rating, if the profile has one. | `4` |
| `reviewCount` | Published rating or review count. | `1` |
| `hours` | Opening hours grouped by weekday. | `{"Monday":["12:30-17:00"]}` |
| `description` | Public business description. | `Especialista en cocido madrileño y besugo.` |
| `images` | Public business image URLs found on the profile. | `[` `"https://multimedia.paginasamarillas.es/adsContentSrv/195495346-2-Gup2MMbbRj/5551a66d-884b-4e5d-aab0-d81dfad1c880/la-daniela-logo.jpg"` `]` |
| `logo` | Business logo URL, when published. | `https://multimedia.paginasamarillas.es/adsContentSrv/195495346-2-Gup2MMbbRj/5551a66d-884b-4e5d-aab0-d81dfad1c880/la-daniela-logo.jpg` |
| `reviews` | Review text excerpts present in profile markup. | `[]` |
| `searchTerm` | Keyword or start URL that generated the row. | `restaurantes` |
| `scrapedAt` | UTC timestamp for this collection. | `2026-10-25T12:00:00Z` |

### How to scrape Paginas Amarillas

1. Enter one or more Spanish business categories or keywords, such as `restaurantes`, `fontaneros`, or `abogados`.
2. Add one or more Spanish cities or provinces. Every term is searched in every location. Leave locations empty to run the category across Spain.
3. Set the maximum number of businesses and pages. Keep profile enrichment enabled to collect rating, hours, coordinates, and any extra public contact details.
4. Start the run. The actor reads directory result pages, opens profiles when requested, removes duplicate listings, and writes business rows to the dataset.
5. Download the dataset as JSON or CSV, or connect it to a scheduled data workflow.

You can also provide a `paginasamarillas.es` search URL or an individual business profile URL in `startUrls`. A search URL is paged from its current page; a profile URL creates one enriched business row. URLs on other hosts are rejected before any request is made.

### Input

| Name | Type | Default | Description |
| --- | --- | --- | --- |
| `searchTerms` | Array of strings | `[` `"restaurantes"` `]` | Categories or terms to search. The terms are combined with every location. |
| `locations` | Array of strings | `[` `"Madrid"` `]` | Spanish cities or provinces. An empty list means nationwide results. |
| `startUrls` | Array of URLs | None | Directory search or business profile URLs on `paginasamarillas.es`. |
| `maxItems` | Integer | `50` | Maximum unique businesses across the entire run. |
| `scrapeDetails` | Boolean | `true` | Open each profile to collect available rating, hours, coordinates, contact, and image data. |
| `maxPages` | Integer | `20` | Maximum pages to read per search. Each result page contains about 30 businesses. |
| `maxConcurrency` | Integer | `5` | Maximum concurrent network requests. Accepted values are 1 through 20. |
| `proxy` | Object | Platform proxy | Optional proxy configuration for cloud runs. Requests rotate sessions and can escalate to residential routing when blocked. |

#### Example input

```json
{
  "searchTerms": ["restaurantes", "cafeterias"],
  "locations": ["Madrid", "Barcelona"],
  "maxItems": 100,
  "maxPages": 5,
  "maxConcurrency": 5,
  "scrapeDetails": true
}
```

This example starts four searches: two terms across two locations. The actor stops after 100 unique listings even if the searches have more pages available. For a nationwide search, set `locations` to an empty array. For a quick run that only needs phone and address data, turn off `scrapeDetails` to skip profile requests.

### Output example

This example is one row from the verified Madrid restaurant run. The sample is shortened only where the full field is not needed to show the output structure.

```json
{
  "listingId": "195495346",
  "slug": "la-daniela-cuchilleros",
  "name": "La Daniela Cuchilleros",
  "paginasAmarillasUrl": "https://www.paginasamarillas.es/f/madrid/la-daniela-cuchilleros_195495346_000000002.html",
  "isPremium": true,
  "phone": "913662018",
  "phones": ["913662018"],
  "fax": null,
  "email": null,
  "website": "http://www.tabernadeladaniela.com?utm_campaign=paginasamarillas&utm_source=paginasamarillas&utm_medium=referral",
  "social": [
    "https://facebook.com/LADANIELACUCHILLEROS",
    "https://www.facebook.com/paginasamarillases/"
  ],
  "address": "Calle de los Cuchilleros, 9 , 28005 , Madrid",
  "street": "Calle de los Cuchilleros, 9",
  "postalCode": "28005",
  "city": "Madrid",
  "region": "Madrid",
  "country": "Spain",
  "latitude": 40.414341585,
  "longitude": -3.70799292,
  "category": "Cocina madrileña Cocina castellana | Restaurante",
  "categories": ["Cocina madrileña Cocina castellana | Restaurante"],
  "rating": 4,
  "reviewCount": 1,
  "hours": {
    "Monday": ["12:30-17:00", "20:30-00:00"],
    "Tuesday": ["12:30-17:00", "20:30-00:00"],
    "Wednesday": ["12:30-17:00", "20:30-00:00"],
    "Thursday": ["12:30-17:00", "20:30-00:00"],
    "Friday": ["12:30-17:00", "20:30-00:00"],
    "Saturday": ["13:00-17:30", "20:30-00:00"],
    "Sunday": ["13:00-17:30", "20:30-00:00"]
  },
  "description": "Especialista en cocido madrileño y besugo. Cerveza tirada al estilo antiguo. Vermut de barril. Imprescindible hacer reservas.",
  "images": [
    "https://multimedia.paginasamarillas.es/adsContentSrv/195495346-2-Gup2MMbbRj/5551a66d-884b-4e5d-aab0-d81dfad1c880/la-daniela-logo.jpg"
  ],
  "logo": "https://multimedia.paginasamarillas.es/adsContentSrv/195495346-2-Gup2MMbbRj/5551a66d-884b-4e5d-aab0-d81dfad1c880/la-daniela-logo.jpg",
  "reviews": [],
  "searchTerm": "restaurantes",
  "scrapedAt": "2026-10-25T16:54:56Z"
}
```

### Use cases

- **Sales teams** can build a starting list of local businesses by category and city, then prioritize rows with a public phone number or website.
- **Agencies** can compare business coverage across multiple Spanish cities and trades using one consistent set of columns.
- **Local search consultants** can map directory categories, paid placements, public ratings, and business websites within a service area.
- **Market researchers** can estimate how many listed providers appear for a category and compare addresses, categories, and profile completeness.
- **Franchise and location teams** can collect nearby businesses for territory research, partner discovery, or site planning.
- **Data operations teams** can refresh public business directory rows on a schedule and compare later exports for changes.

Use the data to support research and prioritization. A directory listing is not proof that a business is currently open, accepts new customers, or has verified every published detail; confirm important facts with the business before relying on them.

### How much does it cost to scrape Paginas Amarillas?

Estimate listing collection at **$5 per 1,000 unique businesses**. This rate is aligned with the prevailing price for comparable directory data. At that rate, 1,000 listings cost about $5, 5,000 cost about $25, and 10,000 cost about $50. These examples scale linearly with the number of unique rows returned.

The estimate covers the listing event and standard platform usage for a typical run. Your actual total can vary if the run uses more memory, takes longer, or escalates to a billed residential proxy. Profile enrichment makes additional requests but does not create extra dataset rows; set `scrapeDetails` to `false` when you only need the search-card fields. The actor stops at `maxItems`, which lets you choose a predictable result ceiling before a run starts.

For a small test, use `maxItems: 50` and one search term with one city. At the same reference rate, 50 rows correspond to roughly $0.25 in listing events. A broader study can use several locations and a larger ceiling; reduce the cap if the combined term-by-location searches would otherwise return more data than you need. Check the run's usage and billing details for the final charge.

### Tips for best results

- Use the category wording people would enter in the directory. Spanish terms such as `fontaneros`, `electricistas`, and `restaurantes` are useful starting points.
- Search a city and province using the spelling most commonly used locally. Accents are accepted in inputs and normalized for the directory URL.
- Keep `maxItems` at or below the number of records you plan to review. The cap applies across every search and prevents unexpectedly large exports.
- Increase `maxPages` when a category has enough results to reach beyond the first page. Pages are read in sequence from each search URL, and the actor stops when the page has no new records.
- Leave `scrapeDetails` enabled when opening hours, coordinates, rating, email, social links, or profile images matter. Disable it when a quick name-phone-address list is enough.
- Use a lower `maxConcurrency` if the site responds slowly or if the run is collecting many profiles. Raise it gradually for larger runs; the default of five is suitable for a typical search.
- Use `startUrls` when you already have an exact directory search or a list of profile pages. For a search URL, paging begins at the page number in that URL.
- The actor deduplicates by listing identifier across pages and search terms. A listing that matches two terms appears once, with the term that first produced it recorded in `searchTerm`.
- For a repeatable city comparison, keep the same terms, page limit, enrichment setting, and result ceiling across runs.

### Limits

Search pages expose about 30 listings at a time. The actor follows numbered result pages up to `maxPages`, whose maximum is 400, and also stops when `maxItems` is reached. A category may have fewer results than the cap or may end before the requested page limit.

Paginas Amarillas returns server-rendered directory markup. Search cards contain the most consistent identity, phone, website, description, category, and address details. Rating, hours, coordinates, email, social profiles, images, logo, fax, and review text depend on what each business profile publishes. Some profile pages also render the directory's own social links; check account ownership before treating a social URL as belonging to the listed business. Missing email or review text is common and is returned as `null` or an empty list rather than guessed.

The current extraction is for the Spain domain `paginasamarillas.es`. It does not accept Latin American directory domains or unrelated directory sites. Search URL patterns, profile markup, pagination, and anti-bot behavior can change over time; if the site changes its page structure, some fields may become sparse until extraction is updated.

Profile enrichment requests one profile page per listing and therefore takes longer than search-card-only collection. A slow profile or temporary request failure does not discard a valid search-card row. A run that returns no business rows fails with a message asking you to check the term, city, or URL, so an empty successful dataset is not treated as a useful result.

### Use with AI agents (MCP)

Add this actor to any MCP client (Claude, Cursor, VS Code, n8n and others) with one URL:

`https://mcp.apify.com?tools=mlg14/paginasamarillas-scraper`

Returns one dataset item per business with name, phone, address, website, opening hours, rating and coordinates when the profile publishes them. Keep results bounded with `maxItems`.

**Prompt 1:** "Find 30 restaurants in Madrid with phone numbers and addresses."

```json
{
  "searchTerms": [
    "restaurantes"
  ],
  "locations": [
    "Madrid"
  ],
  "maxItems": 30,
  "scrapeDetails": false
}
```

**Prompt 2:** "Collect up to 50 plumbers in Valencia with full profile details."

```json
{
  "searchTerms": [
    "fontaneros"
  ],
  "locations": [
    "Valencia"
  ],
  "maxItems": 50,
  "scrapeDetails": true
}
```

**Prompt 3:** "Get the full profile of this business on Paginas Amarillas."

```json
{
  "startUrls": [
    {
      "url": "https://www.paginasamarillas.es/f/madrid/la-daniela-cuchilleros_195495346_000000002.html"
    }
  ],
  "maxItems": 1
}
```

### FAQ

**Is it legal to collect these listings?** The actor reads public business directory pages. You are responsible for following the site's terms, applicable privacy and data-protection law, and the rules that apply to your use. Use public business information only for a lawful purpose, avoid personal-data misuse, and do not treat a public contact field as consent for unsolicited outreach.

**Do I need a proxy?** Cloud runs may need proxy routing if the directory challenges or blocks a request. The actor uses rotating request sessions and can escalate to residential routing after a block. A proxy does not guarantee access; very large jobs should be run with sensible page, item, and concurrency limits.

**How fast is a run?** A search-only run reads result pages and is usually quicker than an enriched run. With `scrapeDetails` on, profile pages are fetched concurrently, up to the `maxConcurrency` setting. Response times and the number of records determine the actual duration, so begin with a small cap when estimating a larger job.

**Can I schedule or monitor a scrape?** Yes. Schedule the actor through your automation environment and use run status, dataset links, and webhooks to monitor completion. Keep the input stable between runs when you want to compare coverage over time.

**Can I export the results to a spreadsheet?** Download the dataset as CSV or JSON. CSV can be opened by common spreadsheet applications, and JSON is useful for scripts and data pipelines. The `hours`, `phones`, `social`, `categories`, `images`, and `reviews` fields are arrays or objects; choose JSON if you need to preserve those nested values without flattening them.

**Why is an email or rating empty?** The directory does not publish every field for every business. The actor returns `null` for unavailable scalar fields and an empty array for lists with no public values. Profile enrichment can expose additional details, but it cannot fill information the page does not provide.

**Can I scrape one business profile?** Yes. Add the public profile URL to `startUrls`, leave the search settings at their defaults or clear them, and keep `scrapeDetails` enabled. The result uses the same flat output shape as a business found through search.

**Does it support non-Spain sites?** No. This actor accepts search and profile URLs on `paginasamarillas.es`. It does not target country-specific domains in Latin America or other yellow-page directories.

### Integrations

Run the actor through its API, connect completion webhooks to your pipeline, or pass the dataset to a workflow automation service. CSV exports can feed spreadsheet applications; JSON can feed databases, dashboards, and custom applications. Schedule recurring runs for the categories and locations you monitor, and compare each completed dataset with the prior run to identify newly listed businesses or changed public details.

### Support

Open an issue on the Issues tab; we reply within 24h and add fields on request. Include the input, the affected profile or search URL, and the field that needs attention. Do not include private credentials or personal information in an issue.

# Actor input Schema

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

Business categories or keywords to search. Example: \["restaurantes", "fontaneros", "abogados"]. Each term is searched in every location; leave locations empty for a nationwide search.

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

Spanish cities or provinces. Example: \["Madrid", "Barcelona", "Valencia"]. Leave empty for a nationwide category search.

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

paginasamarillas.es search or business profile URLs. Example: \[{"url": "https://www.paginasamarillas.es/f/madrid/la-daniela-cuchilleros_195495346_000000002.html"}]. Use to scrape a known page; other hosts are rejected.

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

Stop after this many unique businesses across all searches. Example: 50. Use a small value for quick runs; the default keeps typical runs compact.

## `scrapeDetails` (type: `boolean`):

Open each listing profile to collect rating, hours, coordinates and extra contact details. Example: true. Set false for faster runs with only the data on search cards.

## `maxPages` (type: `integer`):

Maximum result pages to read per search. Example: 20. Each page holds about 30 businesses. Use a lower value to bound large searches.

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

Maximum concurrent page and profile requests, 1 to 20. Example: 5. Use lower values to be gentler and higher values to finish sooner.

## `proxy` (type: `object`):

Optional proxy settings for cloud runs. Example: {"useApifyProxy": true}. Requests use rotating sessions and escalate to residential routing if the site blocks them.

## Actor input object example

```json
{
  "searchTerms": [
    "restaurantes"
  ],
  "locations": [
    "Madrid"
  ],
  "maxItems": 50,
  "scrapeDetails": true,
  "maxPages": 20,
  "maxConcurrency": 5,
  "proxy": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

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

All unique business listings in the default dataset.

# 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": [
        "restaurantes"
    ],
    "locations": [
        "Madrid"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("mlg14/paginasamarillas-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": ["restaurantes"],
    "locations": ["Madrid"],
}

# Run the Actor and wait for it to finish
run = client.actor("mlg14/paginasamarillas-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": [
    "restaurantes"
  ],
  "locations": [
    "Madrid"
  ]
}' |
apify call mlg14/paginasamarillas-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mlg14/paginasamarillas-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/u7BSLFig7eERmokPP/builds/25nkY16yF9au0OIsf/openapi.json
