# PsychologyToday.com Search and Details scraper (`memo23/psychologytoday-scraper`) Actor

Scrape PsychologyToday by state, city or direct profile URL for therapists, psychiatrists, groups and treatment-rehab. Returns name, credentials, bio, address, phone, image, specialties, expertise, types of therapy, insurance carriers, license, client focus and nearby areas.

- **URL**: https://apify.com/memo23/psychologytoday-scraper.md
- **Developed by:** [Muhamed Didovic](https://apify.com/memo23) (community)
- **Categories:** Automation, Lead generation, Agents
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, NaN bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.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

## Psychology Today Therapist Scraper

**Turn Psychology Today into a structured therapist database.** Scrape every therapist on a directory page — name, credentials, full bio, specialties, accepted insurance, license number, fees, location and more — from any `/us/therapists/{state}/{city}` page, or scrape a single therapist by profile URL.

![Psychology Today Scraper - How It Works](https://raw.githubusercontent.com/muhamed-didovic/muhamed-didovic.github.io/main/assets/how-it-works-psychologytoday.png)

### ✨ Why use this scraper?

Psychology Today rate-limits aggressively, has no public API, and renders different sections per profile. This actor handles all of that.

- 🎯 **Three starting points.** Paste city directory URLs, paste direct therapist profile URLs, or supply `stateCode` + `citySlug` and the actor builds the directory URL.
- 👥 **One row per therapist.** Each dataset item merges JSON-LD (clean structured data) with HTML extraction (the parts JSON-LD doesn't cover).
- 🛡️ **Resilient fetch pipeline.** Every request races `impit` (Firefox TLS, HTTP/3 when no proxy) against `got-scraping`. Each retry rotates the proxy. Built for sites that rate-limit aggressively.
- 🧾 **Listing card preserved.** When a therapist is discovered through a directory page, the original LIST-card data is kept under `basicInfo` on the row.
- 🔁 **Built-in retry on rate limits.** 4xx responses rotate the proxy and retry — typical runs come through 22/22 even on heavily blocked IPs.
- 📦 **No browser.** Pure HTTP + Cheerio. Cheap, fast, low memory.

### 📖 Overview

This is a **Psychology Today therapist scraper**. It is built around the directory page format (`/us/therapists/{state}/{city}`) and produces **one structured row per therapist** found on those listing pages.

- Start from one or many city directory URLs.
- The actor paginates each URL (`?page=2`, `?page=3`, …) up to a configurable cap.
- For every therapist card on every page, the actor fetches that therapist's profile page and pushes a single dataset row.
- Each row contains the JSON-LD identity block, the long bio, every visible HTML section (specialties, expertise, types of therapy, client focus, insurance, fees, license, location, nearby areas) and the original listing card under `basicInfo`.

It is **not** a search engine for therapist names across the whole site. The starting point is always a city directory page.

### 🌐 Supported inputs

#### Starting URLs

Two URL types are accepted in `startUrls` — mix them in any combination:

| Type | Pattern | Example | Behavior |
| --- | --- | --- | --- |
| **City directory** | `/us/therapists/{state}/{city}` | `https://www.psychologytoday.com/us/therapists/ny/new-york` | Paginates `?page=2`, `?page=3`, … and fetches every therapist found |
| **Direct profile** | `/us/therapists/{slug}/{numericId}` | `https://www.psychologytoday.com/us/therapists/i-wang-new-york-ny/1392436` | Scrapes that one therapist; `basicInfo` is `null` (no listing-card data available) |

The actor classifies each URL automatically by checking whether the last path segment is numeric.

```json
{
    "startUrls": [
        "https://www.psychologytoday.com/us/therapists/ny/new-york",
        "https://www.psychologytoday.com/us/therapists/ca/los-angeles",
        "https://www.psychologytoday.com/us/therapists/i-wang-new-york-ny/1392436"
    ]
}
````

#### Filter mode (used when `startUrls` is empty)

```json
{
    "stateCode": "ca",
    "citySlug": "san-francisco"
}
```

`stateCode` is the lowercase two-letter US state code, `citySlug` is the city as it appears in the URL. This mode only builds **city directory** URLs — to scrape an individual therapist by ID, pass the profile URL in `startUrls`.

#### Unsupported

- Insurance / specialty / language filters at the actor level — apply those filters on Psychology Today first, then paste the filtered URL into `startUrls`.
- International directories outside `psychologytoday.com/us/...`.
- Search by therapist name across the whole site.

### 🎯 Use cases

| Team | What they build |
|------|----------------|
| **Mental health marketplaces** | Coverage maps showing therapist density by city, specialty, and insurance carrier |
| **Insurance & benefits** | Provider network audits — who actually accepts your plan in a given metro |
| **B2B lead gen** | Outbound lists for selling SaaS, billing tools, or marketing services to therapy practices |
| **Research teams** | Datasets for academic studies on therapy access, fee distribution, and demographic coverage |
| **Health-tech founders** | Competitor and supply-side analysis when sizing a market |
| **Marketing agencies** | Therapist persona research from real bios, specialties, and client-focus tiles |

### ⚙️ How it works

1. **You provide** one or more URLs — city directory, profile, or both — or a `stateCode` + `citySlug`.
2. **For each city directory URL**, the actor fetches the LIST page and extracts every `.results-row` therapist card on it (~20 per page), then walks `?page=2`, `?page=3`, … until `maxItems` or `maxPages` is reached.
3. **For each direct profile URL** in `startUrls`, the actor fetches that one therapist directly with no LIST stage.
4. **Every page fetch races `impit` against `got-scraping`** in parallel. The first one that returns clean HTML wins. Each retry rotates the proxy.
5. **Each therapist becomes one dataset row** combining JSON-LD + HTML extraction. Therapists discovered through a LIST page also keep the original listing-card data under `basicInfo`; therapists scraped via a direct profile URL get `basicInfo: null`.

### 📥 Input configuration

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `startUrls` | string\[] | — | PT therapist directory URLs and/or direct profile URLs. Take priority over filter mode. |
| `stateCode` | string | — | Two-letter state code (lowercase), e.g. `ny`. Used only when `startUrls` is empty. |
| `citySlug` | string | — | City slug as it appears in the URL, e.g. `new-york`. Used with `stateCode`. |
| `maxItems` | integer | `1000` | Stop after this many therapist profiles have been pushed. |
| `maxPages` | integer | `25` | Hard cap on listing pagination per directory URL. |
| `detailConcurrency` | integer | `6` | How many therapist profile pages to fetch in parallel. |
| `maxRequestRetries` | integer | `5` | Per-request retry budget. The actor multiplies this internally because each retry rotates the proxy. |
| `proxy` | object | Apify Residential | Proxy configuration. Residential is strongly recommended. |

#### Examples

**Single city:**

```json
{
    "startUrls": ["https://www.psychologytoday.com/us/therapists/ny/new-york"],
    "maxItems": 100
}
```

**Multiple cities + a direct profile URL, in one run:**

```json
{
    "startUrls": [
        "https://www.psychologytoday.com/us/therapists/ny/new-york",
        "https://www.psychologytoday.com/us/therapists/ca/san-francisco",
        "https://www.psychologytoday.com/us/therapists/i-wang-new-york-ny/1392436"
    ],
    "maxItems": 500,
    "detailConcurrency": 4,
    "proxy": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

**Filter mode:**

```json
{
    "stateCode": "tx",
    "citySlug": "austin",
    "maxItems": 50
}
```

**Single therapist by URL only:**

```json
{
    "startUrls": ["https://www.psychologytoday.com/us/therapists/i-wang-new-york-ny/1392436"],
    "maxItems": 1
}
```

### 📤 Output overview

- One dataset row per therapist.
- Top-level fields are merged from JSON-LD (canonical structured data) and HTML extraction.
- Nested objects: `license`, `address`, `clientFocus`, `nearbyAreas`.
- The original listing-card data is preserved under `basicInfo` on every row.
- Items are written to `storage/datasets/default/` and additionally exported as a single `data.json` at the project root after the run.

### 📋 Output sample

Trimmed real row (from `data.json`):

```jsonc
{
    "profileUrl": "https://www.psychologytoday.com/us/therapists/dani-saliani-new-york-ny/914610",
    "name": "Dani Saliani",
    "jobTitle": "Counselor",
    "credentials": "Counselor, LMHC-D, MA",
    "honorificSuffix": "LMHC-D, MA",
    "image": "https://photos.psychologytoday.com/.../320x400.jpeg",
    "description": "You can keep it together, but inside, you feel stuck...",
    "telephone": "(929) 930-5468",
    "verifiedByPsychologyToday": true,
    "acceptsInsurance": true,
    "topSpecialties": ["ADHD", "Anxiety", "Men's Issues"],
    "expertise": ["Body Image", "Career Counseling", "Codependency", "Depression", "..."],
    "typesOfTherapy": ["Compassion Focused", "Eclectic", "Family Systems", "..."],
    "clientFocus": {
        "Age": ["Teen", "Adults"],
        "Communities": ["Gay Allied", "Non-Binary Allied", "Queer Allied", "Racial Justice Allied"]
    },
    "insurance": ["Aetna", "Cigna and Evernorth", "Out of Network"],
    "yearsInPractice": 7,
    "license": { "number": "011817", "issuingState": "New York", "expires": "2026-11-01" },
    "address": { "locality": "New York", "region": "New York", "postalCode": "10010", "country": "US" },
    "primaryLocation": "1133 Broadway, New York, NY 10010",
    "nearbyAreas": {
        "cities": ["Brooklyn, NY", "New York, NY"],
        "counties": ["Kings", "New York"],
        "zips": ["10001", "10003", "10010", "11222"]
    },
    "basicInfo": {
        "name": "Dani Saliani",
        "title": "Counselor, LMHC-D, MA",
        "address": "New York, NY 10010",
        "shortDescription": "You can keep it together, but inside, you feel stuck...",
        "image": "https://photos.psychologytoday.com/.../320x400.jpeg",
        "detailsUrl": "https://www.psychologytoday.com/us/therapists/dani-saliani-new-york-ny/914610",
        "phone": "(929) 930-5468"
    }
}
```

### 🗂️ Key output fields

#### Identity

| Field | Type | Description |
|-------|------|-------------|
| `profileUrl` | string | Therapist profile URL (the URL fetched). |
| `name` | string | Full name (JSON-LD, fallback to `.profile-title`). |
| `jobTitle` | string | Profession (e.g. `Counselor`, `Psychologist`). |
| `credentials` | string | Title line including post-nominals. |
| `honorificSuffix` | string | Letters only (e.g. `PhD`, `LMHC-D, MA`). |
| `image` | string | Profile photo URL. |
| `telephone` | string | From JSON-LD; may be empty even when the listing has one. |
| `verifiedByPsychologyToday` | boolean | True if the "Verified" badge is on the profile. |

#### Bio & specialties

| Field | Type | Description |
|-------|------|-------------|
| `description` | string | Long bio paragraph. |
| `topSpecialties` | string\[] | The 1–3 specialties PT highlights. |
| `expertise` | string\[] | Full list of issues treated. |
| `typesOfTherapy` | string\[] | Modalities (CBT, DBT, ACT, EMDR, …). |
| `clientFocus` | object | Map of group title → values (`Age`, `Participants`, `Communities`, …). |
| `knowsAboutRaw` | string | Original comma-separated `knowsAbout` string from JSON-LD. |

#### Insurance & practice

| Field | Type | Description |
|-------|------|-------------|
| `acceptsInsurance` | boolean | Convenience flag from the at-a-glance row. |
| `insurance` | string\[] | Named insurance carriers (may include `Out of Network`). |
| `yearsInPractice` | number | null | Parsed from the education section, `null` if not displayed. |
| `license.number` | string | State license number. |
| `license.issuingState` | string | State that issued the license. |
| `license.expires` | string | Expiration date (`YYYY-MM-DD`). |

#### Location

| Field | Type | Description |
|-------|------|-------------|
| `primaryLocation` | string | Single-line address as displayed on the page. |
| `address.locality` | string | City. |
| `address.region` | string | State (full name). |
| `address.postalCode` | string | ZIP. |
| `address.country` | string | Country code or name. |
| `nearbyAreas.cities` | string\[] | Cities the therapist also serves. |
| `nearbyAreas.counties` | string\[] | Counties covered. |
| `nearbyAreas.zips` | string\[] | Zip codes covered. |

#### Listing card (preserved under `basicInfo`)

| Field | Type | Description |
|-------|------|-------------|
| `name`, `title`, `address`, `shortDescription`, `image`, `detailsUrl`, `phone` | string | Exactly what was visible on the directory listing card before the DETAIL fetch. `address` may be `Online Only` for virtual therapists. |

### ❓ FAQ

**Which Psychology Today URLs are supported?**
City directory URLs of the form `https://www.psychologytoday.com/us/therapists/{state}/{city}`. Direct therapist profile URLs are *not* supported as input — the actor expects directory pages and discovers profiles from them.

**Can I scrape multiple cities at once?**
Yes — pass several URLs in `startUrls`. Pagination, `maxItems`, and `maxPages` apply per start URL.

**Does the actor support filtering by insurance, specialty, or language?**
Not at the actor level. Apply Psychology Today's own filters on the website first, then paste the resulting URL into `startUrls`. Pagination on filtered URLs works the same way.

**How is `basicInfo` different from the top-level fields?**
`basicInfo` is what the listing card showed *before* the DETAIL request fired. Top-level fields are the richer DETAIL-page data. Some fields only exist on the listing card (`shortDescription`); some only on the DETAIL page (full `description`, `license`, `clientFocus`, `insurance`, etc.); some are duplicated for convenience. When a therapist is scraped via a direct profile URL (no LIST stage), `basicInfo` is `null`.

**How does the actor handle Psychology Today's rate limiting?**
Every request races `impit` (Firefox TLS fingerprint, HTTP/3 when no proxy) against `got-scraping` in parallel. The first one returning clean HTML wins. Each retry rotates to a fresh proxy IP. On heavily blocked IPs you'll typically see "Recovered on attempt 2 via …" lines — that's the rotation working.

**What happens when a profile section is missing?**
Lists come back as `[]`, optional objects come back as `null`, optional strings as `""`. PT profiles are not uniform — not every therapist displays Top Specialties, years in practice, or every client-focus group.

**Can I run this without an Apify residential proxy?**
You can run with `useApifyProxy: false`, but PT rate-limits IPs aggressively and the per-attempt rotation has nothing to rotate to — every retry comes from the same banned IP. Residential proxy is strongly recommended.

**Are paginated profiles re-fetched if a city is bigger than `maxItems`?**
The actor stops as soon as `maxItems` is reached on the dataset. Subsequent listing pages are not fetched.

### 📬 Support

- **Issues** — open one on the actor's repository / Issues tab.
- **Custom work** — need extra fields, different start strategies, or a tailored CSV export? Reach out and we can extend the scraper.

Response time: usually under 24 hours.

### 🛠️ Additional services

- Custom field extraction (e.g. raw-HTML capture for downstream NLP, accept-superbill flag, languages spoken).
- Cron-style monitoring runs on saved start URLs.
- Tailored exports (CSV with flattened nested objects, Parquet, BigQuery uploads).

### 🔎 Explore more scrapers

Looking for related directory or marketplace scrapers? The same two-stage LIST → DETAIL pattern with the optional internal-handler engine is reusable; ask for a tailored build.

# Actor input Schema

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

Examples:
• State-wide: https://www.psychologytoday.com/us/therapists/new-york
• State + city: https://www.psychologytoday.com/us/therapists/ny/new-york
• Direct profile: https://www.psychologytoday.com/us/therapists/i-wang-new-york-ny/1392436

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

Choose which type of directory to scrape from PsychologyToday.

## `stateCodes` (type: `array`):

Pick one or more states (2-letter code). Each code is translated to PT's full state slug and used to build `/us/{category}/{slug}`. Leave empty if you supplied **Listing or profile URLs** above.

## `zipCodes` (type: `array`):

Optional 5-digit US ZIP codes. Builds `/us/{category}/{zip}` per ZIP. Combined with **U.S. States** if both are set.

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

Stops after this many therapist profiles have been pushed to the dataset. Pagination ends automatically when the budget is reached.

## `detailConcurrency` (type: `integer`):

How many therapist profile pages to fetch in parallel. Listing pages are always fetched sequentially.

## `maxRequestRetries` (type: `integer`):

Per-request retry budget. The actor multiplies this internally because each retry rotates the proxy.

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

Proxy used by the scraper. Apify Residential is strongly recommended — Psychology Today rate-limits aggressively by IP.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.psychologytoday.com/us/therapists/ny/new-york"
  ],
  "category": "therapists",
  "stateCodes": [
    "ny"
  ],
  "maxItems": 1000,
  "detailConcurrency": 6,
  "maxRequestRetries": 5,
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# 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 = {
    "startUrls": [
        "https://www.psychologytoday.com/us/therapists/ny/new-york"
    ],
    "proxy": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("memo23/psychologytoday-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 = {
    "startUrls": ["https://www.psychologytoday.com/us/therapists/ny/new-york"],
    "proxy": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("memo23/psychologytoday-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 '{
  "startUrls": [
    "https://www.psychologytoday.com/us/therapists/ny/new-york"
  ],
  "proxy": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call memo23/psychologytoday-scraper --silent --output-dataset

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "PsychologyToday.com Search and Details scraper",
        "description": "Scrape PsychologyToday by state, city or direct profile URL for therapists, psychiatrists, groups and treatment-rehab. Returns name, credentials, bio, address, phone, image, specialties, expertise, types of therapy, insurance carriers, license, client focus and nearby areas.",
        "version": "0.0",
        "x-build-id": "vr79LKPIcRl2Aleb9"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/memo23~psychologytoday-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-memo23-psychologytoday-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/memo23~psychologytoday-scraper/runs": {
            "post": {
                "operationId": "runs-sync-memo23-psychologytoday-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/memo23~psychologytoday-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-memo23-psychologytoday-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",
                "properties": {
                    "startUrls": {
                        "title": "Listing or profile URLs",
                        "type": "array",
                        "description": "Examples:\n• State-wide: https://www.psychologytoday.com/us/therapists/new-york\n• State + city: https://www.psychologytoday.com/us/therapists/ny/new-york\n• Direct profile: https://www.psychologytoday.com/us/therapists/i-wang-new-york-ny/1392436",
                        "items": {
                            "type": "string"
                        }
                    },
                    "category": {
                        "title": "Category",
                        "enum": [
                            "therapists",
                            "psychiatrists",
                            "groups",
                            "treatment-rehab"
                        ],
                        "type": "string",
                        "description": "Choose which type of directory to scrape from PsychologyToday.",
                        "default": "therapists"
                    },
                    "stateCodes": {
                        "title": "US States",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Pick one or more states (2-letter code). Each code is translated to PT's full state slug and used to build `/us/{category}/{slug}`. Leave empty if you supplied **Listing or profile URLs** above.",
                        "items": {
                            "type": "string",
                            "enum": [
                                "al",
                                "ak",
                                "az",
                                "ar",
                                "ca",
                                "co",
                                "ct",
                                "de",
                                "dc",
                                "fl",
                                "ga",
                                "hi",
                                "id",
                                "il",
                                "in",
                                "ia",
                                "ks",
                                "ky",
                                "la",
                                "me",
                                "md",
                                "ma",
                                "mi",
                                "mn",
                                "ms",
                                "mo",
                                "mt",
                                "ne",
                                "nv",
                                "nh",
                                "nj",
                                "nm",
                                "ny",
                                "nc",
                                "nd",
                                "oh",
                                "ok",
                                "or",
                                "pa",
                                "ri",
                                "sc",
                                "sd",
                                "tn",
                                "tx",
                                "ut",
                                "vt",
                                "va",
                                "wa",
                                "wv",
                                "wi",
                                "wy"
                            ],
                            "enumTitles": [
                                "Alabama",
                                "Alaska",
                                "Arizona",
                                "Arkansas",
                                "California",
                                "Colorado",
                                "Connecticut",
                                "Delaware",
                                "District of Columbia",
                                "Florida",
                                "Georgia",
                                "Hawaii",
                                "Idaho",
                                "Illinois",
                                "Indiana",
                                "Iowa",
                                "Kansas",
                                "Kentucky",
                                "Louisiana",
                                "Maine",
                                "Maryland",
                                "Massachusetts",
                                "Michigan",
                                "Minnesota",
                                "Mississippi",
                                "Missouri",
                                "Montana",
                                "Nebraska",
                                "Nevada",
                                "New Hampshire",
                                "New Jersey",
                                "New Mexico",
                                "New York",
                                "North Carolina",
                                "North Dakota",
                                "Ohio",
                                "Oklahoma",
                                "Oregon",
                                "Pennsylvania",
                                "Rhode Island",
                                "South Carolina",
                                "South Dakota",
                                "Tennessee",
                                "Texas",
                                "Utah",
                                "Vermont",
                                "Virginia",
                                "Washington",
                                "West Virginia",
                                "Wisconsin",
                                "Wyoming"
                            ]
                        },
                        "default": [
                            "ny"
                        ]
                    },
                    "zipCodes": {
                        "title": "ZIP Codes",
                        "uniqueItems": true,
                        "type": "array",
                        "description": "Optional 5-digit US ZIP codes. Builds `/us/{category}/{zip}` per ZIP. Combined with **U.S. States** if both are set.",
                        "items": {
                            "type": "string",
                            "pattern": "^\\d{5}$"
                        }
                    },
                    "maxItems": {
                        "title": "Maximum number of therapist profiles to scrape",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Stops after this many therapist profiles have been pushed to the dataset. Pagination ends automatically when the budget is reached.",
                        "default": 1000
                    },
                    "detailConcurrency": {
                        "title": "DETAIL concurrency",
                        "minimum": 1,
                        "maximum": 30,
                        "type": "integer",
                        "description": "How many therapist profile pages to fetch in parallel. Listing pages are always fetched sequentially.",
                        "default": 6
                    },
                    "maxRequestRetries": {
                        "title": "Max Request Retries",
                        "type": "integer",
                        "description": "Per-request retry budget. The actor multiplies this internally because each retry rotates the proxy.",
                        "default": 5
                    },
                    "proxy": {
                        "title": "Proxy configuration",
                        "type": "object",
                        "description": "Proxy used by the scraper. Apify Residential is strongly recommended — Psychology Today rate-limits aggressively by IP.",
                        "default": {
                            "useApifyProxy": true,
                            "apifyProxyGroups": [
                                "RESIDENTIAL"
                            ]
                        }
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
