# Thumbtack Pro Scraper (`moving_beacon-owner1/thumbtack-pro-scraper`) Actor

Scrape service providers from Thumbtack across categories like plumbers, cleaners, electricians, photographers, and more. Extract ratings, reviews, pricing, hires, response times, business details, categories, and profile data with city, state, and ZIP-based scraping modes.

- **URL**: https://apify.com/moving\_beacon-owner1/thumbtack-pro-scraper.md
- **Developed by:** [Jamshaid Arif](https://apify.com/moving_beacon-owner1) (community)
- **Categories:** Lead generation, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $10.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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Thumbtack Pro Scraper

Scrapes service provider listings from [Thumbtack](https://www.thumbtack.com) — handymen, plumbers, electricians, cleaners, photographers, and ~25 other service categories — across the US.


### What you get per pro

~20 fields including:

- **Identity**: business name, profile URL, avatar image, "Top Pro" badge
- **Reviews**: rating, review count, qualifier ("Exceptional", "Excellent", "Great"), one featured review
- **Hire signals**: total hires, average response time, urgency pills ("In high demand", "Great value")
- **Pricing**: hourly rate, price range
- **Business info**: full description, founding year, employee count, city, state
- **Categorization**: every category and ZIP this pro surfaced under

### Iteration modes

Thumbtack only returns 10 pros per page in the initial HTML. To get more, the actor offers four modes:

| Mode | Loops over | Requests | Typical pro count |
|---|---|---|---|
| **single** | nothing | 1 | ~10 |
| **related** | related categories | ~27 | 30–80 |
| **zips** | ZIP codes | ~15 | 40–100 |
| **wide** | categories × ZIPs | 50–400 | 100–400 |

### Area control

Three ways to scope the search (pick one):

1. **state + city** (`"tx"`, `"austin"`) — hits Thumbtack's canonical city URL
2. **zipCode** (`"78701"`) — overrides Thumbtack's IP geolocation
3. **zips** (`["10001", "10011", "10025"]`) — required for `mode=zips` or `mode=wide`

If none provided, Thumbtack falls back to the actor's IP geolocation.

### Important: anti-bot

Thumbtack runs **Akamai Bot Manager**. From a datacenter IP (default Apify IP pool), you'll hit HTTP 202 challenges within a few minutes of scraping.

**Strongly recommended**: enable Apify Proxy with the `RESIDENTIAL` group. The input schema defaults to this. Without residential, expect rate limiting after ~10-30 requests.

### Example inputs

#### Just look up handyman pros in Austin

```json
{
    "categorySlug": "handyman",
    "mode": "single",
    "state": "tx",
    "city": "austin"
}
````

#### Get every handyman-adjacent pro in Las Vegas

```json
{
    "categorySlug": "handyman",
    "mode": "related",
    "state": "nv",
    "city": "las-vegas",
    "maxCategories": 15,
    "sleepBetween": 4
}
```

#### Spread across NYC with a custom related-category list

```json
{
    "categorySlug": "house-cleaning",
    "mode": "wide",
    "zips": ["10001", "10011", "10025", "11201", "11215"],
    "relatedCategories": ["deep-house-cleaning-services", "carpet-cleaning"],
    "sleepBetween": 5
}
```

### Output

Results land in the default dataset. Each pro is one item. Use the **Overview** view in Apify Console for a quick table, or **Full record** to see every field.
g

# Actor input Schema

## `categorySlug` (type: `string`):

Thumbtack category slug (e.g. 'handyman', 'house-cleaning', 'plumbers', 'local-electricians'). Lower-case, hyphens.

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

How aggressively to expand the search. 'single' = one request. 'related' = loop over related categories. 'zips' = loop over ZIPs. 'wide' = grid of (categories × ZIPs).

## `state` (type: `string`):

Lowercase US state code. Combine with 'city' for canonical city URL (most reliable). Leave empty if using ZIP-based scopes.

## `city` (type: `string`):

Lowercase, hyphens (e.g. 'austin', 'san-francisco', 'las-vegas'). Used with 'state'.

## `zipCode` (type: `string`):

5-digit US ZIP. Overrides state+city. Used by mode='single' or 'related' when no state+city given.

## `zips` (type: `array`):

List of 5-digit US ZIPs. Required for mode='zips' or 'wide'. Each ZIP returns a different 10-pro slice.

## `relatedCategories` (type: `array`):

Override the built-in RELATED\_CATEGORIES list. If empty, uses the built-in mapping for categorySlug. Only used by mode='related' or 'wide'.

## `maxCategories` (type: `integer`):

Cap on how many category slugs to iterate. Lower = faster but fewer pros. Leave empty for all.

## `maxZips` (type: `integer`):

Cap on how many ZIPs to iterate. Lower = faster but less coverage. Leave empty for all.

## `sleepBetween` (type: `integer`):

Politeness delay. Recommended >= 4 without proxy, >= 2 with residential proxy. Akamai will challenge faster scrapers.

## `impersonate` (type: `string`):

Which browser's TLS handshake to mimic. chrome124 is the most stable default.

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

Recommended: Apify Proxy with residential group ('RESIDENTIAL'). Thumbtack runs Akamai Bot Manager — datacenter IPs get challenged fast.

## Actor input object example

```json
{
  "categorySlug": "handyman",
  "mode": "related",
  "state": "tx",
  "city": "austin",
  "zipCode": "78701",
  "zips": [
    "89101",
    "89102",
    "89104"
  ],
  "relatedCategories": [
    "furniture-assembly",
    "tv-wall-mount-install"
  ],
  "maxCategories": 10,
  "maxZips": 5,
  "sleepBetween": 4,
  "impersonate": "chrome124",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}
```

# 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 = {
    "categorySlug": "handyman",
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ],
        "apifyProxyCountry": "US"
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("moving_beacon-owner1/thumbtack-pro-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 = {
    "categorySlug": "handyman",
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
        "apifyProxyCountry": "US",
    },
}

# Run the Actor and wait for it to finish
run = client.actor("moving_beacon-owner1/thumbtack-pro-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "categorySlug": "handyman",
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ],
    "apifyProxyCountry": "US"
  }
}' |
apify call moving_beacon-owner1/thumbtack-pro-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=moving_beacon-owner1/thumbtack-pro-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Thumbtack Pro Scraper",
        "description": "Scrape service providers from Thumbtack across categories like plumbers, cleaners, electricians, photographers, and more. Extract ratings, reviews, pricing, hires, response times, business details, categories, and profile data with city, state, and ZIP-based scraping modes.",
        "version": "0.0",
        "x-build-id": "UPUTLnjop4dkv8VrH"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/moving_beacon-owner1~thumbtack-pro-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-moving_beacon-owner1-thumbtack-pro-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/moving_beacon-owner1~thumbtack-pro-scraper/runs": {
            "post": {
                "operationId": "runs-sync-moving_beacon-owner1-thumbtack-pro-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/moving_beacon-owner1~thumbtack-pro-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-moving_beacon-owner1-thumbtack-pro-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "categorySlug",
                    "mode"
                ],
                "properties": {
                    "categorySlug": {
                        "title": "Primary category slug",
                        "type": "string",
                        "description": "Thumbtack category slug (e.g. 'handyman', 'house-cleaning', 'plumbers', 'local-electricians'). Lower-case, hyphens."
                    },
                    "mode": {
                        "title": "Iteration mode",
                        "enum": [
                            "single",
                            "related",
                            "zips",
                            "wide"
                        ],
                        "type": "string",
                        "description": "How aggressively to expand the search. 'single' = one request. 'related' = loop over related categories. 'zips' = loop over ZIPs. 'wide' = grid of (categories × ZIPs).",
                        "default": "related"
                    },
                    "state": {
                        "title": "State (2-letter code)",
                        "type": "string",
                        "description": "Lowercase US state code. Combine with 'city' for canonical city URL (most reliable). Leave empty if using ZIP-based scopes."
                    },
                    "city": {
                        "title": "City slug",
                        "type": "string",
                        "description": "Lowercase, hyphens (e.g. 'austin', 'san-francisco', 'las-vegas'). Used with 'state'."
                    },
                    "zipCode": {
                        "title": "Single ZIP code",
                        "pattern": "^\\d{5}$",
                        "type": "string",
                        "description": "5-digit US ZIP. Overrides state+city. Used by mode='single' or 'related' when no state+city given."
                    },
                    "zips": {
                        "title": "Multiple ZIP codes",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "List of 5-digit US ZIPs. Required for mode='zips' or 'wide'. Each ZIP returns a different 10-pro slice.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "relatedCategories": {
                        "title": "Related categories (override)",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Override the built-in RELATED_CATEGORIES list. If empty, uses the built-in mapping for categorySlug. Only used by mode='related' or 'wide'.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxCategories": {
                        "title": "Max categories",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Cap on how many category slugs to iterate. Lower = faster but fewer pros. Leave empty for all."
                    },
                    "maxZips": {
                        "title": "Max ZIPs",
                        "minimum": 1,
                        "maximum": 50,
                        "type": "integer",
                        "description": "Cap on how many ZIPs to iterate. Lower = faster but less coverage. Leave empty for all."
                    },
                    "sleepBetween": {
                        "title": "Seconds between requests",
                        "minimum": 0,
                        "maximum": 60,
                        "type": "integer",
                        "description": "Politeness delay. Recommended >= 4 without proxy, >= 2 with residential proxy. Akamai will challenge faster scrapers.",
                        "default": 4
                    },
                    "impersonate": {
                        "title": "Browser TLS fingerprint",
                        "enum": [
                            "chrome124",
                            "chrome131",
                            "chrome120",
                            "edge101",
                            "safari17_0",
                            "firefox133"
                        ],
                        "type": "string",
                        "description": "Which browser's TLS handshake to mimic. chrome124 is the most stable default.",
                        "default": "chrome124"
                    },
                    "proxyConfiguration": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Recommended: Apify Proxy with residential group ('RESIDENTIAL'). Thumbtack runs Akamai Bot Manager — datacenter IPs get challenged fast."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
