# The Knot Scraper \[$1/1K💰] | Wedding Vendor Leads & Reviews (`ahmed_jasarevic/theknot-scraper`) Actor

Pull US wedding vendor leads from The Knot - name, category, city, rating, review count, starting price, phone, email, website, awards and gallery, plus optional vendor reviews.

- **URL**: https://apify.com/ahmed_jasarevic/theknot-scraper.md
- **Developed by:** [Ahmed Jasarevic](https://apify.com/ahmed_jasarevic) (community)
- **Stats:** 3 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 1,000 vendor leads

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

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

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

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

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

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

# README

## The Knot Scraper

Pull **US wedding vendor leads** from [The Knot](https://www.theknot.com) marketplace — vendor name, category, city, rating, review count, starting price, phone, email, website, awards and gallery — plus optional vendor reviews from the public reviews API.

Built for wedding-vendor lead generation, local SEO and directory outreach, wedding-supplier market sizing and competitor research. No headless browser needed.

### What you get

#### Build a wedding vendor lead list

`name`, `categories`, `city`, `state`, `postalCode`, `phone`, `email`, `website` and `profileUrl` on every row. Contact fields require `fetchProfiles: true`, because The Knot does not include them on the category listing page — see [Why profiles cost an extra request](#why-profiles-cost-an-extra-request).

#### Understand each vendor's market position

`adTier`, `vendorTier`, `claimedStatus`, `rating`, `reviewCount` and `startingPriceMin`/`startingPriceMax` tell you who is established, who is actually claiming their profile, and what they charge. `claimedStatus` alone is a strong filter for outreach quality.

#### Price benchmark vendors by city

`startingPrice`, `startingPriceMin`, `startingPriceMax` plus `city` and `state` let you compute real starting-price bands per market per category — the kind of table a wedding magazine or pricing guide is built from.

#### Qualify vendors before you contact them

`serviceArea`, `awards[]`, `galleryImageCount`, `videoCount`, `headline` and `profileEnriched` together give you enough signal to rank a list by likely budget and seriousness before spending a single email.

#### Capture recent review sentiment

`includeReviews: true` calls The Knot's public reviews GraphQL endpoint and writes a second dataset with `rating`, `title`, `content`, `weddingDate` and `reviewerFirstName`.

### How it works

The Knot's marketplace pages are **Redux-rendered** — the category listing ships its vendor list as a serialized Redux payload inside the HTML, plus a Next.js `__NEXT_DATA__` block. The Actor parses that embedded state directly with `CheerioCrawler`, so listing rows cost one plain HTTP request each and no browser is launched.

The Knot returns **30 vendors per page**, which is what `maxListings` (default 30) and `maxPages` (default 1) are calibrated against.

When `fetchProfiles` is enabled, profile pages are independent, so the Actor fetches them **in parallel** via `RequestQueue` at `maxConcurrency` (default 12) — the single biggest speed lever in this Actor. If The Knot starts answering **403 (DataDome)**, lower `maxConcurrency` and raise `requestDelayMs`; those two inputs exist for exactly that.

Every row carries provenance: `source`, `sourceUrl`, `categorySlug`, `locationSlug`, `pageNumber` and `position`, so you can tell which category page and which position on it a lead came from. `profileEnriched` is `true` only when the profile fetch actually succeeded.

#### Why profiles cost an extra request

Phone, email, website, social links, the full description and the gallery **are not present on the category listing page**. They exist only on the individual vendor profile. So `fetchProfiles: true` costs roughly one additional request per vendor — and each one is billed as a `profile-detail` event. Listings alone are never enriched with guessed data.

### Input

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `startUrls` | string\[] | 1 prefilled URL | Category listing URLs or vendor profile URLs. Profile URLs are detected automatically. |
| `maxListings` | integer | `30` | Max vendors per category page. The Knot returns 30 per page. |
| `maxPages` | integer | `1` | Max category pages per start URL. |
| `maxItems` | integer | `200` | Hard cap on total vendor rows. |
| `fetchProfiles` | boolean | `false` | Fetch each profile for phone, email, website, description, gallery. ~1 extra request per vendor, billed as `profile-detail`. |
| `includeReviews` | boolean | `false` | Pull recent reviews into the separate `reviews` dataset. Each review billed as a `review` event. |
| `maxReviewsPerVendor` | integer | `5` | Recent reviews per vendor when `includeReviews` is on. |
| `maxRequestsPerCrawl` | integer | `250` | Hard safety cap on HTTP requests. |
| `maxConcurrency` | integer | `12` | Parallel requests. **Lower this first if you see 403s.** |
| `minConcurrency` | integer | `12` | Floor for the autoscaled pool. Leave as default so runs start at full speed. |
| `requestDelayMs` | integer | `200` | Politeness delay before each request. `0` for max speed. |
| `requestHandlerTimeoutSecs` | integer | `60` | Per-request timeout. |
| `proxy` | object | `{ useApifyProxy: false }` | Standard Apify proxy picker. Use it if DataDome challenges you. |

The default `startUrls` prefills `https://www.theknot.com/marketplace/wedding-photographers-new-york-ny`, so the Actor returns valid data with **zero configuration**.

### Output

**Default dataset — 42 fields, one row per vendor:**

`_meta`, `storefrontId`, `vendorId`, `displayId`, `name`, `profileUrl`, `categories`, `categorySlugs`, `marketCode`, `adTier`, `vendorTier`, `claimedStatus`, `rating`, `reviewCount`, `startingPrice`, `startingPriceMin`, `startingPriceMax`, `phone`, `email`, `website`, `social`, `address`, `city`, `state`, `postalCode`, `country`, `serviceArea`, `headline`, `description`, `awards`, `galleryImages`, `galleryImageCount`, `videoCount`, `source`, `sourceUrl`, `categorySlug`, `locationSlug`, `pageNumber`, `position`, `profileEnriched`, `reviewTotal`, `scrapedAt`

**Reviews dataset — 13 fields, one row per review:**

`storefrontId`, `vendorName`, `vendorProfileUrl`, `reviewId`, `rating`, `title`, `content`, `createdAt`, `weddingDate`, `reviewerFirstName`, `reviewerLastName`, `reviewerRole`, `scrapedAt`

Dataset views ship as **Vendor leads** (default) and **Reviews**.

Field notes that change how you read the data:

- `phone`, `email`, `website`, `social`, `description`, `awards`, `galleryImages`, `galleryImageCount`, `videoCount` and `headline` are only populated when `fetchProfiles: true`. With the default `false`, expect them `null` or empty — that is by design, not a failure.
- `startingPrice` is the rendered string ("$3,500"); `startingPriceMin` and `startingPriceMax` are the numeric bounds. Use the numeric fields for maths.
- `reviewCount` comes from the listing page; `reviewTotal` is the authoritative count when profiles were fetched. A difference means the listing was stale.
- `claimedStatus` tells you whether the vendor claims their own listing. Unclaimed vendors are usually less reliable to contact.
- `position` is the vendor's index on that page (1–30), which is a legitimate input if you ever want top-of-page bias.

### Example input

First run, zero configuration:

```json
{}
```

Leads with contact details — the normal lead-gen setup:

```json
{
  "startUrls": ["https://www.theknot.com/marketplace/wedding-photographers-new-york-ny"],
  "fetchProfiles": true,
  "maxItems": 100,
  "maxPages": 2
}
```

Multi-category sweep with review sentiment:

```json
{
  "startUrls": [
    "https://www.theknot.com/marketplace/wedding-photographers-new-york-ny",
    "https://www.theknot.com/marketplace/wedding-planners-austin-tx",
    "https://www.theknot.com/marketplace/wedding-florists-chicago-il"
  ],
  "fetchProfiles": true,
  "includeReviews": true,
  "maxReviewsPerVendor": 5,
  "maxItems": 300,
  "maxConcurrency": 8,
  "requestDelayMs": 350
}
```

Fast, listing-only pass — cheapest possible per lead:

```json
{
  "startUrls": ["https://www.theknot.com/marketplace/wedding-caterers-los-angeles-ca"],
  "fetchProfiles": false,
  "maxListings": 30,
  "maxItems": 500,
  "maxPages": 5
}
```

### Example output

```json
{
  "_meta": { "url": "https://www.theknot.com/marketplace/wedding-photographers-new-york-ny" },
  "storefrontId": "SF-1145772",
  "vendorId": "V-88213",
  "displayId": "studiostilllife-ny",
  "name": "Studio Still Life",
  "profileUrl": "https://www.theknot.com/vendors/studio-still-life--88213",
  "categories": ["Wedding Photographers"],
  "categorySlugs": ["wedding-photographers"],
  "marketCode": "US-NY",
  "adTier": "premium",
  "vendorTier": "platinum",
  "claimedStatus": "claimed",
  "rating": 4.9,
  "reviewCount": 87,
  "startingPrice": "$3,500",
  "startingPriceMin": 3500,
  "startingPriceMax": 9500,
  "phone": "+1 (212) 555-0147",
  "email": "hello@studiostilllife.com",
  "website": "https://studiostilllife.com",
  "social": ["https://instagram.com/studiostilllife", "https://facebook.com/studiostilllife"],
  "address": "214 Wythe Ave, Brooklyn, NY",
  "city": "New York",
  "state": "NY",
  "postalCode": "11249",
  "country": "US",
  "serviceArea": "New York, Brooklyn, Jersey City",
  "headline": "Editorial wedding photography for New York couples",
  "description": "Documentary-style wedding photography with an editorial eye. Available for weddings across NYC and the Hudson Valley.",
  "awards": ["Best of Wedding Awards 2025 - Photography"],
  "galleryImages": ["https://www.theknot.com/tier2/photos/88213-01.jpg"],
  "galleryImageCount": 42,
  "videoCount": 2,
  "source": "category",
  "sourceUrl": "https://www.theknot.com/marketplace/wedding-photographers-new-york-ny",
  "categorySlug": "wedding-photographers",
  "locationSlug": "new-york-ny",
  "pageNumber": 1,
  "position": 4,
  "profileEnriched": true,
  "reviewTotal": 91,
  "scrapedAt": "2026-10-04T08:02:37.512Z"
}
```

### Integrations & automation

Call it over the Apify API, from Python/JavaScript, the CLI or MCP. Datasets export as JSON, CSV, Excel or XML.

For **lead generation**, one run per `(category, city)` pair is usually enough — vendor inventories change slowly, so weekly or even monthly re-runs are sufficient. Schedule monthly with `fetchProfiles: true`, upsert on `vendorId`, and alert on new vendors appearing in a market you track. For **directory and local-SEO outreach**, filter on `claimedStatus: "claimed"` before you export; unclaimed listings frequently have dead contact details.

Typical pipeline: run on schedule → filter `claimedStatus` + `profileEnriched` → score by `rating`, `reviewCount` and `startingPriceMin` → push to your CRM → log outreach against `vendorId`. For **market sizing**, run listing-only across many categories (cheapest per row) and use `startingPriceMin`/`startingPriceMax` for price bands.

#### What a run costs

Per-event billing, so the only thing that matters is which flags you turn on:

| Configuration | Events | Cost |
| --- | --- | --- |
| Listing only, 200 vendors | 200 × lead | **$0.20** |
| + `fetchProfiles`, 200 vendors | 200 lead + 200 profile | **$0.40** |
| + `includeReviews` (5/vendor), 200 vendors | 200 + 200 + 1,000 | **$0.90** |
| Single page, 30 vendors, profiles + 5 reviews | 30 + 30 + 150 | **$0.135** |

### Related Actors

| Actor | Why |
| --- | --- |
| [`dionysus_way/the-knot-marketplace-scraper---wedding-vendor-leads`](https://apify.com/dionysus_way/the-knot-marketplace-scraper---wedding-vendor-leads) | The market leader here — 95 users, 1.3K runs. The reference point for pricing and field coverage. |
| [`apage/the-knot-scraper`](https://apify.com/apage/the-knot-scraper) | Redux-state extraction as well, category + keyword modes. |
| [`kawsar/the-knot-marketplace-scraper`](https://apify.com/kawsar/the-knot-marketplace-scraper) | Earlier listing-focused implementation, useful for schema comparison. |
| [`ahmed_jasarevic/taskrabbit-scraper`](https://apify.com/ahmed_jasarevic/taskrabbit-scraper) | Same job shape in a different vertical: local service provider listings with contact data and reviews. |
| [`ahmed_jasarevic/europages-scraper`](https://apify.com/ahmed_jasarevic/europages-scraper) | B2B directory extraction across 200+ countries, with the same profile-enrichment pattern. |

### FAQ

#### How does this compare to the main The Knot scraper?

On price per 1,000 leads, [dionysus_way's Actor](https://apify.com/dionysus_way/the-knot-marketplace-scraper---wedding-vendor-leads) lists at **$3.90/1K** while this one is **$1.00/1K** — roughly a quarter of the cost. Beyond price, this Actor parses the embedded Redux state and fetches profile pages in parallel at `maxConcurrency` (default 12), which is where most of the wall-clock saving comes from. It also separates reviews into their own dataset and reports `claimedStatus`, `vendorTier` and `reviewTotal` so you can qualify leads rather than just collect them. Prices are a snapshot — check the live table on each Actor page before committing.

#### Why are phone, email and website empty by default?

Because they aren't on the category page. The Knot only exposes contact details on individual vendor profiles, so `fetchProfiles` must be `true` — that costs roughly one extra request per vendor, and each is billed as a `profile-detail` event. The Actor never fabricates or infers contact data.

#### Why am I getting 403 errors?

That's DataDome. Lower `maxConcurrency` (try 4–6) and raise `requestDelayMs` (try 500–1000). If it persists, enable `proxy`. Do not raise concurrency to fix a 403 — it makes the blocking worse.

#### Can I scrape a specific vendor's profile instead of a category?

Yes. Put profile URLs in `startUrls` — they are detected automatically, and the Actor skips the listing stage for them.

#### How many vendors per page should I expect?

30. That is why `maxListings` defaults to 30. To go deeper, raise `maxPages` rather than `maxListings`, since a single page never yields more than 30.

#### Does it include reviews?

Yes, with `includeReviews: true`. Reviews go to a **separate** `reviews` dataset, fetched from The Knot's public reviews GraphQL endpoint, capped by `maxReviewsPerVendor` (default 5). Each review is billed at $0.0005, so enabling reviews is usually the largest contributor to run cost.

#### Can I use this for cold outreach to these vendors?

That is a legitimate lead-gen use of public business listing data, and it is what this Actor is built for. But The Knot's Terms of Service govern use of their marketplace data, and both CAN-SPAM and TCPA (if you dial US numbers) apply to unsolicited outreach. Read the disclaimer below before you build a campaign on it.

### SEO Keywords

the knot scraper, theknot.com, wedding vendor leads, wedding photographer leads, wedding vendor database, wedding vendor directory data, wedding supplier contacts, local seo wedding leads, wedding florist lead generation, wedding planner leads, wedding photography data, wedding vendor emails, wedding business directory, wedding market research, us wedding vendor pricing, wedding vendor reviews, venue lead generation, florist phone numbers, photographer lead list, wedding directory api, claimed business leads, local business contact data, wedding supplier outreach

### For AI Agents & LLM Apps

Returns US wedding vendor listings from The Knot as flat dataset rows, one per vendor, with optional profile enrichment and a separate reviews dataset.

**Minimal input** — smallest input that produces a valid run (startUrls has a default prefill):

```json
{ "maxItems": 30 }
```

**Lead-gen run** — contact details included:

```json
{ "startUrls": ["https://www.theknot.com/marketplace/wedding-photographers-new-york-ny"], "fetchProfiles": true, "maxItems": 100 }
```

**With review sentiment**:

```json
{ "fetchProfiles": true, "includeReviews": true, "maxReviewsPerVendor": 5, "maxItems": 300, "maxConcurrency": 8 }
```

**Output fields — vendors (42):** \_meta, storefrontId, vendorId, displayId, name, profileUrl, categories, categorySlugs, marketCode, adTier, vendorTier, claimedStatus, rating, reviewCount, startingPrice, startingPriceMin, startingPriceMax, phone, email, website, social, address, city, state, postalCode, country, serviceArea, headline, description, awards, galleryImages, galleryImageCount, videoCount, source, sourceUrl, categorySlug, locationSlug, pageNumber, position, profileEnriched, reviewTotal, scrapedAt

**Output fields — reviews (13):** storefrontId, vendorName, vendorProfileUrl, reviewId, rating, title, content, createdAt, weddingDate, reviewerFirstName, reviewerLastName, reviewerRole, scrapedAt

**Behaviours an agent should know**

- Two datasets: `default` (vendors) and `reviews`. The `reviews` dataset is only populated with `includeReviews: true`; otherwise it comes back empty.
- `fetchProfiles` defaults to **false**, so `phone`, `email`, `website`, `social`, `description`, `awards` and gallery fields are null on a default run. If you need contact data, you must set it — and it adds a billed `profile-detail` event per vendor. `profileEnriched` tells you per row whether the fetch actually succeeded.
- `startUrls` accepts category URLs **and** profile URLs; profile URLs are detected automatically and skip the listing stage.
- 403 responses come from DataDome. If you see them, **lower** `maxConcurrency` and **raise** `requestDelayMs`. Never raise concurrency to resolve a 403.
- `startingPrice` is a formatted string; use `startingPriceMin` / `startingPriceMax` for arithmetic.
- `maxItems` (default 200) caps vendors; `maxRequestsPerCrawl` (default 250) is the hard safety net that will stop a run before `maxItems` if requests run out.
- Billing: **$0.001 per lead**, **$0.001 per profile detail**, **$0.0005 per review**. With profiles + 5 reviews/vendor the effective cost per vendor is ~$0.0045, not $0.001 — budget accordingly.

### Legal & Compliance

This Actor is an independent third-party tool. It is not affiliated with, endorsed by, or sponsored by The Knot or OneWed, Inc., and it is not a substitute for any vendor listing you obtain through The Knot's own program.

**What it actually accesses:** publicly visible The Knot marketplace category pages, vendor profile pages and public reviews endpoints, over plain HTTP, with no login, no authentication bypass, no captcha solving and no paywall circumvention. No headless browser is launched.

**Personal and business contact data:** with `fetchProfiles: true` this Actor collects business contact information — `phone`, `email`, `website`, `social` — plus business names and addresses, from listings The Knot publishes for vendors specifically so that couples can contact them for wedding services. `reviewerFirstName`/`reviewerLastName` in the reviews dataset are consumer names attached to public reviews.

**Your obligations.** B2B outreach to businesses using published business contact details is lawful in many jurisdictions, but it is regulated. The **TCPA** restricts unsolicited autodialed or prerecorded calls to US numbers, and **CAN-SPAM** requires accurate headers, a physical postal address and a working opt-out on commercial email. GDPR and similar regimes apply if you target EU-based vendors. Vendors who have claimed their The Knot profile have asked to be contacted; vendors with `claimedStatus: "unclaimed"` have not necessarily consented to anything, so treat them more carefully. Do not resell the collected contact data as a list, and do not merge it into purchased data-broking datasets.

You are solely responsible for compliance with The Knot's Terms of Service, applicable anti-spam and telemarketing law, and data-protection law. Keep volumes polite: `maxRequestsPerCrawl` (default 250) and `requestDelayMs` (default 200) bound a run, and lowering `maxConcurrency` when challenged is expected behaviour, not an error.

# Actor input Schema

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

The Knot category listing URLs or vendor profile URLs to scrape, e.g. https://www.theknot.com/marketplace/wedding-photographers-new-york-ny. Profile URLs are detected automatically. Enable 'Fetch full profiles' to enrich listing vendors with contact details.

## `maxListings` (type: `integer`):

Maximum number of vendor listings to pull from each category page before paging. The Knot returns 30 vendors per page.

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

Maximum number of paginated category pages to fetch per start URL.

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

Hard cap on total vendor records pushed to the dataset.

## `fetchProfiles` (type: `boolean`):

Fetch each vendor's full profile page to collect phone, email, website and social links, and to attach the complete description and gallery. Those fields are not present on the category listing page. Roughly one extra request per vendor. Each profile fetch is billed as a 'profile-detail' event.

## `includeReviews` (type: `boolean`):

Call the public The Knot reviews GraphQL API and store up to 'maxReviewsPerVendor' recent reviews per vendor in a separate 'reviews' dataset. Each review is billed as a 'review' event.

## `maxReviewsPerVendor` (type: `integer`):

Number of recent reviews to attach per vendor when 'Include review details' is enabled.

## `maxRequestsPerCrawl` (type: `integer`):

Hard safety cap on the number of HTTP requests made by this run.

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

Number of simultaneous HTTP requests. Profile pages are independent, so higher values finish much faster. Lower this if The Knot starts returning 403 (DataDome).

## `minConcurrency` (type: `integer`):

Floor for the autoscaled pool. Leave at the default so the run starts at full speed instead of ramping up.

## `requestDelayMs` (type: `integer`):

Politeness delay inserted before each request. Set 0 for maximum speed, raise it if requests start failing.

## `requestHandlerTimeoutSecs` (type: `integer`):

Per-request timeout.

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

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "startUrls": [
    "https://www.theknot.com/marketplace/wedding-photographers-new-york-ny"
  ],
  "maxListings": 30,
  "maxPages": 1,
  "maxItems": 200,
  "fetchProfiles": false,
  "includeReviews": false,
  "maxReviewsPerVendor": 5,
  "maxRequestsPerCrawl": 250,
  "maxConcurrency": 12,
  "minConcurrency": 12,
  "requestDelayMs": 200,
  "requestHandlerTimeoutSecs": 60,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `vendorLeads` (type: `string`):

No description

## `reviews` (type: `string`):

No description

# 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.theknot.com/marketplace/wedding-photographers-new-york-ny"
    ],
    "maxListings": 30,
    "maxPages": 1,
    "maxItems": 200,
    "maxReviewsPerVendor": 5,
    "maxRequestsPerCrawl": 250,
    "maxConcurrency": 12,
    "minConcurrency": 12,
    "requestDelayMs": 200,
    "requestHandlerTimeoutSecs": 60,
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/theknot-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.theknot.com/marketplace/wedding-photographers-new-york-ny"],
    "maxListings": 30,
    "maxPages": 1,
    "maxItems": 200,
    "maxReviewsPerVendor": 5,
    "maxRequestsPerCrawl": 250,
    "maxConcurrency": 12,
    "minConcurrency": 12,
    "requestDelayMs": 200,
    "requestHandlerTimeoutSecs": 60,
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/theknot-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 '{
  "startUrls": [
    "https://www.theknot.com/marketplace/wedding-photographers-new-york-ny"
  ],
  "maxListings": 30,
  "maxPages": 1,
  "maxItems": 200,
  "maxReviewsPerVendor": 5,
  "maxRequestsPerCrawl": 250,
  "maxConcurrency": 12,
  "minConcurrency": 12,
  "requestDelayMs": 200,
  "requestHandlerTimeoutSecs": 60,
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/theknot-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,ahmed_jasarevic/theknot-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/G8N5HrdQ1cb2mJB7Q/builds/1dCx46ZilBPEvXgKn/openapi.json
