# Thailand Yellow Pages Scraper (`crawlerbros/thailand-yellow-pages-scraper`) Actor

Scrape yellowpages.co.th - Thailand's official business directory. Search by keyword and province, browse official business categories, or enrich specific listings with phone numbers, hours, and coordinates.

- **URL**: https://apify.com/crawlerbros/thailand-yellow-pages-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Lead generation, Automation, Other
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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

## Thailand Yellow Pages Scraper

Scrape [yellowpages.co.th](https://www.yellowpages.co.th) — Thailand's official business directory. Search by keyword and province, browse an official business category ("heading"), or enrich specific listings with phone numbers, business hours, and precise coordinates. No login, no cookies, no paid proxy required.

### What this actor does

- **Three modes:** `search`, `byCategory`, `byProfileUrls`
- **Province filter:** restrict search results to any of Thailand's 77 official provinces
- **Category browse:** walk the site's official business-category taxonomy (e.g. "Restaurants", "Hotels", "Auto Repair & Service")
- **Contact enrichment:** optionally visit each business's own directory page to add phone number, business hours, and a fuller street address
- **Bilingual:** browse the Thai or English edition of the site
- **Empty fields are omitted** — every record only contains the data actually found for that business

### Output per business

- `businessId` — the directory's internal business identifier
- `name` — business name
- `category`, `categoryUrl` — the official directory category and its browse URL
- `address` — address as shown in the directory (district/sub-district/province/postal code, and full street address when enriched or fetched from mode=`byProfileUrls`)
- `province` — one of Thailand's 77 provinces, parsed from the address
- `postalCode` — 5-digit Thai postal code
- `latitude`, `longitude` — coordinates parsed from the listing's Google Maps link
- `description` — the business's own product/service description
- `phone` — phone number (only when the business has a native directory profile page and contact enrichment was requested, or in `byProfileUrls` mode)
- `fax` — fax number (same conditions as `phone`, when the business lists one)
- `businessHours` — opening hours text (same conditions as `phone`)
- `lineId` — LINE messenger ID (same conditions as `phone`, when the business lists one)
- `facebookUrl` — Facebook page URL (same conditions as `phone`, when the business lists one)
- `imageUrl` — listing photo, when the business uploaded one
- `profileUrl` — the business's yellowpages.co.th profile page (when it has one)
- `websiteUrl` — the business's own external website (when the directory links out directly instead of hosting a profile page)
- `sourceUrl` — canonical URL for this record (`profileUrl` or `websiteUrl`, whichever applies)
- `customerId`, `headingCode`, `addressId` — additional directory identifiers (only present when a profile page was fetched)
- `recordType` — `businessListing` or `businessProfile`
- `scrapedAt` — UTC timestamp

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | select | `search` | `search` / `byCategory` / `byProfileUrls` |
| `query` | string | `restaurant` | Keyword, business name, or phone number to search for (mode=`search`) |
| `province` | select | – | Restrict to one of Thailand's 77 provinces (mode=`search`) |
| `category` | string | `Restaurants & Food Shops` | Exact official category/heading name to browse (mode=`byCategory`) |
| `profileUrls` | array | – | Full yellowpages.co.th profile URLs, or bare numeric business IDs (mode=`byProfileUrls`) |
| `language` | select | `th` | `th` or `en` — which site edition to browse (mode=`search` only; `byCategory` always matches against the English heading name) |
| `includeContactDetails` | boolean | `true` | Visit each result's own profile page to add phone/hours (search/byCategory only) |
| `maxItems` | int | `30` | Hard cap on returned records (1–1000) |

#### Example: search restaurants in Bangkok, with phone numbers

```json
{
  "mode": "search",
  "query": "restaurant",
  "province": "Bangkok",
  "includeContactDetails": true,
  "maxItems": 50
}
```

#### Example: browse an entire category

```json
{
  "mode": "byCategory",
  "category": "Hotels (Bangkok Metro)",
  "maxItems": 100
}
```

#### Example: enrich specific listings

```json
{
  "mode": "byProfileUrls",
  "profileUrls": [
    "https://www.yellowpages.co.th/profile/หยินหยาง-คลินิกฝังเข็ม-93ITTdSAL",
    "523342900374001"
  ]
}
```

### Use cases

- **Lead generation** — build a list of businesses in a given city/province and category
- **Market research** — measure business density by category across Thailand's provinces
- **Sales prospecting** — collect phone numbers and addresses for a target vertical
- **Directory aggregation** — sync a category into your own local-search product
- **Location intelligence** — plot business coordinates on a map for coverage analysis

### FAQ

**Which businesses get a `phone` and `businessHours`?** Only businesses that have a native directory profile page on yellowpages.co.th. Businesses that link straight out to their own website (shown as `websiteUrl` instead of `profileUrl`) don't have that page, so phone/hours aren't available for them from this source.

**Why does `facebookUrl` sometimes fail to load when I open it directly?** Facebook blocks all non-browser (curl/bot) traffic to its pages with a generic error, even for real, active pages — this is Facebook's own platform-wide anti-scraping behavior, not a broken link. The URL itself is exactly what the business listed on yellowpages.co.th and will open normally in a real browser.

**What does the `province` filter actually match?** It's passed straight through to the directory's own search, which matches province, district, sub-district, or postal-code text — so results are as accurate as the directory's own search engine.

**Can I search in Thai script?** Yes — `query` and `category` both accept Thai text directly (e.g. `category: "คลินิกฝังเข็ม"`).

**Why do some records have `address` but not `province` or `postalCode`?** Those two fields are parsed from the address text; if a listing's address doesn't include a recognizable province name or a trailing 5-digit postal code, only the raw `address` is kept.

**Does `language: "en"` translate business names?** No — business names and descriptions are stored exactly as the business entered them (usually Thai). For mode=`search`, `language` changes whether address text renders in Thai or English. Mode=`byCategory` always fetches the English edition internally (regardless of `language`) so that the category name you provide can be reliably matched against each result's own category — this is why `category` should always be typed in English (e.g. `Restaurants & Food Shops`, not a Thai translation).

**Is this actor reliable?** Yes — yellowpages.co.th serves plain server-rendered HTML with no JavaScript challenge or CAPTCHA, so the actor uses plain HTTP requests with automatic retries on rate limits/server errors. No proxy is required.

# Actor input Schema

## `mode` (type: `string`):

What to fetch from Thailand Yellow Pages (yellowpages.co.th).

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

Product, service, shop name, company, phone number, or location term to search for, e.g. `restaurant`, `hotel`, `plumber`. Matches yellowpages.co.th's own site search.

## `province` (type: `string`):

Restrict search results to one of Thailand's 77 official provinces. Leave as "(none)" to search all of Thailand.

## `category` (type: `string`):

Exact yellowpages.co.th category ("heading") name to browse, in ENGLISH, e.g. `Restaurants & Food Shops`, `Hotels (Bangkok Metro)`, `Automobile Repairing & Service`, `Acupuncture Clinic`. Must match the official heading name exactly (case-insensitive) — browse the full taxonomy at yellowpages.co.th/en/category to find exact names. Results that don't exactly match the requested category are automatically filtered out, so an approximate name (e.g. `Hotels` instead of `Hotels (Bangkok Metro)`) yields 0 records rather than unrelated ones.

## `profileUrls` (type: `array`):

Full yellowpages.co.th business profile URLs (containing `/profile/`), e.g. `https://www.yellowpages.co.th/profile/some-business-93ITTdSAL`. Also accepts the numeric `data-businessid` redirect form `https://www.yellowpages.co.th/profile/523342900374001`.

## `language` (type: `string`):

Which language edition of yellowpages.co.th to browse for mode=search (address text renders in this language). Business names/descriptions are stored as entered by the business (usually Thai) regardless of this setting. Not used by mode=byCategory, which always matches against the English heading name for reliable category filtering.

## `includeContactDetails` (type: `boolean`):

For search/byCategory modes, visit each business's own yellowpages.co.th profile page to add phone number, business hours, and full street address. Only works for businesses that have a native yellowpages.co.th profile page (not ones that link straight out to their own website). Adds one extra request per result.

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

Hard cap on the number of business records returned.

## Actor input object example

```json
{
  "mode": "search",
  "query": "restaurant",
  "province": "Bangkok",
  "category": "Restaurants & Food Shops",
  "profileUrls": [
    "https://www.yellowpages.co.th/profile/หยินหยาง-คลินิกฝังเข็ม-93ITTdSAL"
  ],
  "language": "th",
  "includeContactDetails": true,
  "maxItems": 30
}
```

# Actor output Schema

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

Dataset containing all scraped business listings.

# 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 = {
    "mode": "search",
    "query": "restaurant",
    "province": "Bangkok",
    "category": "Restaurants & Food Shops",
    "profileUrls": [
        "https://www.yellowpages.co.th/profile/หยินหยาง-คลินิกฝังเข็ม-93ITTdSAL"
    ],
    "language": "th",
    "includeContactDetails": true,
    "maxItems": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/thailand-yellow-pages-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 = {
    "mode": "search",
    "query": "restaurant",
    "province": "Bangkok",
    "category": "Restaurants & Food Shops",
    "profileUrls": ["https://www.yellowpages.co.th/profile/หยินหยาง-คลินิกฝังเข็ม-93ITTdSAL"],
    "language": "th",
    "includeContactDetails": True,
    "maxItems": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/thailand-yellow-pages-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 '{
  "mode": "search",
  "query": "restaurant",
  "province": "Bangkok",
  "category": "Restaurants & Food Shops",
  "profileUrls": [
    "https://www.yellowpages.co.th/profile/หยินหยาง-คลินิกฝังเข็ม-93ITTdSAL"
  ],
  "language": "th",
  "includeContactDetails": true,
  "maxItems": 30
}' |
apify call crawlerbros/thailand-yellow-pages-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,crawlerbros/thailand-yellow-pages-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/xp4Xoz4UhBpKltdf0/builds/tPXHBsdHZEzKlqcJk/openapi.json
