# YachtWorld Scraper (`crawlerbros/yachtworld-scraper`) Actor

Scrape YachtWorld - the world's largest yacht & boat marketplace. Search boats for sale with make, model, length, price and year filters, browse by make, fetch full listing details with specifications, engines, broker info and images.

- **URL**: https://apify.com/crawlerbros/yachtworld-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Automation, E-commerce, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.00 / 1,000 results

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

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

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

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## YachtWorld Scraper

Scrape **YachtWorld** — the world's largest marketplace for yachts and boats. Search hundreds of thousands of listings with make, model, length, price and year filters, browse every listing from a manufacturer, or fetch complete detail pages with specifications, engines, broker information and photo galleries.

### What this actor does

- **Three modes:** `search` (keyword + full filter set), `browseByMake` (every listing from one manufacturer), `byUrl` (full detail from a listing or broker URL)
- **Search filters:** make, model, keyword, boat type, new/used condition, fuel type, hull material, hull shape, length range (ft), price range (USD), year range, country, seller type, sort order
- **Full listing detail:** title, price (USD + currency), year, make/model, length, beam, draft, weight, fuel type, hull material/shape, engines (make, model, hours, hp), fuel/water capacities, description, location, broker name/phone, image and video URLs
- **Cross-platform IDs:** IMT, Boat Trader and BCNA listing IDs are captured when YachtWorld exposes them
- **Empty fields are omitted**

### Data source

YachtWorld (yachtworld.com) is owned by Boats Group. The actor reads YachtWorld's public search pages and listing pages.

**Cloudflare caveat:** YachtWorld is protected by Cloudflare. Plain HTTP clients receive `403 Forbidden` (verified), while a full headless browser loads the site normally. This actor therefore runs a real browser (Playwright) for every request. If the datacenter IP is challenged, the optional Apify proxy is engaged automatically and retried with rotating sessions — no user action needed. Image URLs point at the `images.boatsgroup.com` CDN.

**Facet routing:** most search filters are applied through YachtWorld's REST search API. The fuel type / hull material / hull shape facets are *not* accepted by that API (it rejects them with `400`), so the actor automatically switches to the SSR search pages (`/boats-for-sale/fuel-diesel/`, `/hull-steel/`, `/hull-type-modified-vee/`, …) whenever any of those three filters is set — verified live that these path segments filter correctly and can be combined (`type-sail/condition-used/`). In the SSR path a free-text keyword that matches a manufacturer (e.g. `bayliner`) is automatically turned into a `make-…` path segment (`/boats-for-sale/fuel-diesel/make-bayliner/` — verified live), falling back to the plain listing when the hinted page has no boats. If the REST path is interrupted mid-way (0 records, or a throttle mid-pagination) while data exists, the actor recovers through the SSR pages — deduplicating against everything already emitted — before giving up.

### Output per boat

- `listingId` — YachtWorld listing ID
- `title`, `make`, `model`, `year`
- `priceUsd`, `priceCurrency`, `priceHidden`, `previousPriceUsd`, `availability`
- `lengthFt`, `lengthM`, `beamFt`, `draftFt`, `weightLb`/`weightKg`, `dryWeightLb`, `displacementLb`
- `fuelType`, `hullMaterial`, `hullShape`
- `fuelCapacityGal`, `waterCapacityGal`, `holdingCapacityGal`
- `engines[]` — per engine: `make`, `model`, `type`, `hours`, `hp`; plus `totalPowerHp`, `totalEngineHours`
- `city`, `subdivision`, `country`, `postalCode`, `location`
- `brokerName`, `brokerPhone`, `brokerAddress`, `brokerCity`, `brokerCountry`, `brokerStreet`, `brokerPostalCode`, `brokerLatitude`, `brokerLongitude`, `brokerSpotlight`, `brokerLogoUrl`, `brokerActiveListings`, `brokerSoldListings`
- `class` (e.g. `power-pilot`, `sail-racercruiser`), `boatType` (`power` / `sail` / `unpowered`)
- `condition` (`new` / `used`), `sellerType` (`dealer` / `owner`)
- `sponsored`, `featured`, `enhanced` — listing promotion flags
- `attributes` — listing attribute codes (`NEW_ARRIVAL`, `LOCAL_DELIVERY`, …) or label/value pairs when YachtWorld returns them
- `isCurrentModel`, `isOemModel` — model lifecycle flags
- `imageUrls[]`, `videoUrls[]`, `mediaCount`, `imageCount`, `videoCount`
- `description`, `otherDetails`, `specs`
- `imtId`, `boatTraderId`, `bcnaId`, `yachtworldId`
- `sourceUrl`, `recordType: "boat"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `search` | `search` / `browseByMake` / `byUrl` |
| `q` | string | `bayliner` | Free-text keyword: make, model or type (mode=search) |
| `make` | string | – | Constrain to a manufacturer (mode=search) |
| `model` | string | – | Constrain to a model name (mode=search) |
| `browseByMake` | string | `bayliner` | Manufacturer to browse (mode=browseByMake) |
| `urls` | array | – | Listing/broker URLs to fetch (mode=byUrl, duplicates deduped) |
| `boatType` | string | – | `power` / `sail` / `unpowered` |
| `condition` | string | – | `new` / `used` |
| `fuelType` | string | – | `diesel` / `electric` / `petrol` / `other` |
| `hullMaterial` | string | – | `aluminum` / `composite` / `ferrocement` / `fiberglass` / `hypalon` / `other` / `pvc` / `steel` / `wood` |
| `hullShape` | string | – | `catamaran` / `deep-vee` / `modified-vee` / `monohull` |
| `minLength` / `maxLength` | int | – | Length range in feet |
| `minPrice` / `maxPrice` | int | – | Price range in USD |
| `minYear` / `maxYear` | int | – | Model-year range |
| `country` | string | – | ISO 3166-1 alpha-2 country of the listing |
| `sellerType` | string | – | `dealer` / `owner` |
| `sortBy` | string | `recommended` | `recommended`, `created-desc`, `price-asc`, `year-desc`, … |
| `maxItems` | int | `20` | Hard cap (1–200) |
| `proxyConfiguration` | object | Apify proxy | Optional; auto-engaged on Cloudflare challenge |

> Note: when `fuelType` / `hullMaterial` / `hullShape` are used the search runs through the SSR facet pages. `sortBy` and `model` are not part of the facet path — length/price/year/keyword are still enforced locally on every record. When only REST-compatible filters are used, `sortBy` and `model` apply as normal.

#### Example: search with filters

```json
{
  "mode": "search",
  "q": "trawler",
  "boatType": "power",
  "condition": "used",
  "fuelType": "diesel",
  "hullMaterial": "steel",
  "minLength": 40,
  "maxLength": 70,
  "minPrice": 100000,
  "maxPrice": 800000,
  "minYear": 2005,
  "country": "US",
  "sortBy": "price-desc",
  "maxItems": 10
}
```

#### Example: browse all boats from one manufacturer

```json
{
  "mode": "browseByMake",
  "browseByMake": "beneteau",
  "maxItems": 50
}
```

#### Example: fetch full listing details by URL

```json
{
  "mode": "byUrl",
  "urls": [
    "https://www.yachtworld.com/yacht/2000-bayliner-5788-pilot-house-motoryacht-10075370/",
    "https://www.yachtworld.com/yacht/2015-beneteau-first-35-2-carbon-edition-10278657/"
  ]
}
```

### Use cases

- **Yacht dealerships** — monitor competitor inventory, pricing and brokerage positioning
- **Market research** — build price-per-foot benchmarks by make, type, year and region
- **Boat valuation** — track sold-listing history and current asking prices for a model
- **Lead generation** — identify brokers and owners with active inventory in a region
- **Fleet managers** — keep a structured registry of vessels on the market worldwide

### Limitations

- **Cloudflare blocks plain HTTP clients** — YachtWorld returns `403 Forbidden` to plain HTTP clients (verified). The actor runs a real browser (Playwright) for every request and auto-engages the optional Apify proxy on a challenge.
- **Search records are compact cards** — detailed specifications, engines, descriptions and other details are only exposed on the listing detail page (`mode=byUrl`); `specs`, `engines`, `description` and `otherDetails` appear on detail records.
- **Prices can be hidden** — sellers can list without a public price ("Request price"); those records omit the price fields.
- **Facet routing caveat** — when `fuelType` / `hullMaterial` / `hullShape` are used, the search runs through the SSR facet pages where `sortBy` and `model` don't apply (length/price/year/keyword are still enforced locally).
- **`maxItems` is capped at 200** — hard cap is 1–200 per run.
- **Image CDN requires a browser-like client** — `images.boatsgroup.com` URLs return `403` to plain `curl`/`urllib`; fetch them with a real browser or the Apify proxy.

### FAQ

**What is the data source?** YachtWorld.com, the world's largest online marketplace for boats and yachts, operated by Boats Group.

**How fresh is the data?** Every run reads YachtWorld live — records reflect the listing state at scrape time, and `scrapedAt` records exactly when.

**Why does the actor need a browser?** YachtWorld sits behind Cloudflare and returns `403` to plain HTTP clients (verified). A full browser is required; the actor automatically engages the optional Apify proxy if a datacenter IP is challenged.

**Why are some prices missing?** Sellers can list without a public price ("Request price"). Those records simply omit the price fields.

**Why are some fields missing on search records?** Search results are the marketplace's compact card payload — detailed specifications, engine details and descriptions are only exposed on the listing detail page (`mode=byUrl`). The `specs`, `engines`, `description` and `otherDetails` fields appear on detail records.

**What is `boatType`?** YachtWorld groups boats into `power` (motor boats), `sail` (sailboats) and `unpowered` (small boats such as kayaks and tenders).

**Does the data include boat images?** Yes — `imageUrls` lists all gallery image URLs from the boatsgroup.com CDN. The CDN serves the images to real browsers from any network (verified: `200 image/jpeg` via headless Chrome from a clean context on this machine, same IP that gets `403` from plain HTTP clients). Plain `curl`/`urllib` requests get `403 text/html` regardless of User-Agent or Referer — the block is on the client's TLS/fingerprint, not the IP. If your client sees 403s, fetch through a real browser or the Apify proxy.

**Is this affiliated with YachtWorld?** No. This is an independent third-party actor using YachtWorld's public website.

# Actor input Schema

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

What to fetch.

## `q` (type: `string`):

Free-text keyword: make, model or type, e.g. `bayliner`, `beneteau oceanis`, `sail cruiser`.

## `make` (type: `string`):

Constrain results to a boat manufacturer, e.g. `Bayliner`, `Beneteau`, `Sea Ray`.

## `model` (type: `string`):

Constrain results to a specific model name, e.g. `5788`, `Oceanis 46.1`.

## `browseByMake` (type: `string`):

Manufacturer slug to browse all of its listings, e.g. `bayliner`, `beneteau`, `sea-ray`.

## `urls` (type: `array`):

YachtWorld listing (boat) or broker page URLs.

## `boatType` (type: `string`):

Filter by top-level boat category.

## `condition` (type: `string`):

Filter by listing condition.

## `fuelType` (type: `string`):

Filter by engine fuel type (verified YachtWorld facet values). (mode=search)

## `hullMaterial` (type: `string`):

Filter by hull material (verified YachtWorld facet values). (mode=search)

## `hullShape` (type: `string`):

Filter by hull shape (verified YachtWorld facet values). (mode=search)

## `minLength` (type: `integer`):

Only boats at least this long (feet).

## `maxLength` (type: `integer`):

Only boats no longer than this (feet).

## `minPrice` (type: `integer`):

Only boats priced at least this amount (USD).

## `maxPrice` (type: `integer`):

Only boats priced at most this amount (USD).

## `minYear` (type: `integer`):

Only boats built in or after this year.

## `maxYear` (type: `integer`):

Only boats built in or before this year.

## `country` (type: `string`):

Filter by listing country (ISO 3166-1 alpha-2).

## `sellerType` (type: `string`):

Filter by who is selling.

## `sortBy` (type: `string`):

Result ordering.

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

Hard cap on emitted records.

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

Optional. Used automatically if YachtWorld's Cloudflare protection blocks the datacenter IP (403/429). Leave on the free Apify proxy.

## Actor input object example

```json
{
  "mode": "search",
  "q": "bayliner",
  "browseByMake": "bayliner",
  "urls": [],
  "sortBy": "recommended",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `boats` (type: `string`):

Dataset containing all scraped YachtWorld boat listings.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "mode": "search",
    "q": "bayliner",
    "browseByMake": "bayliner",
    "urls": [],
    "sortBy": "recommended",
    "maxItems": 20,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/yachtworld-scraper").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "mode": "search",
    "q": "bayliner",
    "browseByMake": "bayliner",
    "urls": [],
    "sortBy": "recommended",
    "maxItems": 20,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/yachtworld-scraper").call(run_input=run_input)

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

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

```

## CLI example

```bash
echo '{
  "mode": "search",
  "q": "bayliner",
  "browseByMake": "bayliner",
  "urls": [],
  "sortBy": "recommended",
  "maxItems": 20,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/yachtworld-scraper --silent --output-dataset

```

## MCP server setup

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