Yachtr APIyachtr.com ↗
Retrieve boat listing details from yachtr.com: specs, engine data, images, price, location, and broker contact info via a single API endpoint.
What is the Yachtr API?
The Yachtr.com API provides access to boat listing data through one endpoint, get_boat_details, returning over 10 structured fields per listing including specifications, engine details, images, price, location, and broker contact information. You can query any listing by passing either the full yachtr.com URL or the numeric vessel ID extracted from the URL path, making it straightforward to integrate individual listing lookups into fleet comparison tools, marine marketplaces, or brokerage workflows.
curl -X GET 'https://api.parse.bot/scraper/aa1e2835-2f90-48a2-b0c0-5a81ce39f795/get_boat_details' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace yachtr-com-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""
Yachtr Boat Details API Client
Get your API key from: https://parse.bot/settings
"""
import os
import requests
from typing import Optional, Dict, Any, List
class ParseClient:
"""Client for interacting with Parse API scrapers."""
def __init__(self, api_key: Optional[str] = None):
"""
Initialize the Parse API client.
Args:
api_key: API key for authentication. If not provided, reads from PARSE_API_KEY env var.
"""
self.base_url = "https://api.parse.bot"
self.scraper_id = "aa1e2835-2f90-48a2-b0c0-5a81ce39f795"
self.api_key = api_key or os.getenv("PARSE_API_KEY")
if not self.api_key:
raise ValueError("API key must be provided or set in PARSE_API_KEY environment variable")
def _call(self, endpoint: str, method: str = "POST", **params) -> Dict[str, Any]:
"""
Make a request to the Parse API.
Args:
endpoint: The endpoint name
method: HTTP method (GET or POST)
**params: Parameters to send with the request
Returns:
Parsed JSON response
Raises:
requests.RequestException: If the request fails
"""
url = f"{self.base_url}/scraper/{self.scraper_id}/{endpoint}"
headers = {
"X-API-Key": self.api_key,
"Content-Type": "application/json"
}
if method.upper() == "GET":
response = requests.get(url, headers=headers, params=params)
elif method.upper() == "POST":
payload = params
response = requests.post(url, headers=headers, json=payload)
else:
raise ValueError(f"Unsupported HTTP method: {method}")
response.raise_for_status()
return response.json()
def get_boat_details(self, boat_id: str) -> Dict[str, Any]:
"""
Get comprehensive details of a boat listed on yachtr.com.
Args:
boat_id: Either a full yachtr.com boat listing URL or the numeric vessel ID
Returns:
Dictionary containing boat specifications, engine info, images, and broker contact
Example:
>>> client = ParseClient()
>>> details = client.get_boat_details("2850869")
>>> print(details["title"])
"""
return self._call("get_boat_details", method="GET", boat_id=boat_id)
def format_boat_info(boat: Dict[str, Any]) -> str:
"""Format boat information for display."""
output = []
output.append(f"\n{'='*60}")
output.append(f"BOAT: {boat.get('title', 'N/A')}")
output.append(f"{'='*60}")
output.append(f"Name: {boat.get('boat_name', 'N/A')}")
output.append(f"Location: {boat.get('location', 'N/A')}")
output.append(f"Price: ${boat.get('price_usd', 'N/A')}")
output.append(f"\nSPECIFICATIONS:")
specs = boat.get('specifications', {})
for key, value in specs.items():
output.append(f" {key}: {value}")
engines = boat.get('engines', [])
if engines:
output.append(f"\nENGINES:")
for engine in engines:
output.append(f" {engine.get('name', 'Unknown')}:")
output.append(f" Make: {engine.get('Engine Make', 'N/A')}")
output.append(f" Model: {engine.get('Engine Model', 'N/A')}")
output.append(f" HP: {engine.get('Power HP', 'N/A')}")
output.append(f" Hours: {engine.get('Hours', 'N/A')}")
broker = boat.get('broker', {})
if broker:
output.append(f"\nBROKER CONTACT:")
output.append(f" Name: {broker.get('name', 'N/A')}")
output.append(f" Brokerage: {broker.get('brokerage', 'N/A')}")
output.append(f" Email: {broker.get('email', 'N/A')}")
images = boat.get('images', [])
if images:
output.append(f"\nIMAGES: {len(images)} available")
for i, img_url in enumerate(images[:3], 1):
output.append(f" {i}. {img_url}")
if len(images) > 3:
output.append(f" ... and {len(images) - 3} more")
description = boat.get('description', '')
if description:
desc_preview = description[:200] + "..." if len(description) > 200 else description
output.append(f"\nDESCRIPTION:")
output.append(f" {desc_preview}")
output.append(f"\n{'='*60}\n")
return "\n".join(output)
if __name__ == "__main__":
# Initialize the client
client = ParseClient()
# Example workflow: Retrieve details for multiple boats
# Using different boat IDs - could come from a search or user input
boat_ids = [
"2850869", # Ted Brewer 44' sailboat example
# Add more boat IDs as needed
]
print("\n🚤 YACHTR BOAT DETAILS RETRIEVAL")
print("Fetching comprehensive information for listed boats...\n")
# Collection to store retrieved boats
retrieved_boats = []
for boat_id in boat_ids:
try:
print(f"Fetching details for boat ID: {boat_id}...")
# Get boat details from API
boat_details = client.get_boat_details(boat_id)
retrieved_boats.append(boat_details)
# Display formatted information
print(format_boat_info(boat_details))
except requests.RequestException as e:
print(f"❌ Error retrieving boat {boat_id}: {e}\n")
except ValueError as e:
print(f"❌ Invalid data for boat {boat_id}: {e}\n")
# Summary report
if retrieved_boats:
print(f"\n📊 SUMMARY")
print(f"{'='*60}")
print(f"Total boats retrieved: {len(retrieved_boats)}")
# Calculate average price
prices = []
for boat in retrieved_boats:
try:
price_str = boat.get('price_usd', '0').replace('$', '').replace(',', '')
price = float(price_str)
if price > 0:
prices.append(price)
except (ValueError, TypeError):
pass
if prices:
avg_price = sum(prices) / len(prices)
print(f"Average price: ${avg_price:,.0f}")
print(f"Price range: ${min(prices):,.0f} - ${max(prices):,.0f}")
# Broker summary
brokers = set()
for boat in retrieved_boats:
broker_name = boat.get('broker', {}).get('brokerage', 'Unknown')
brokers.add(broker_name)
print(f"Brokerages represented: {len(brokers)}")
for broker in sorted(brokers):
print(f" - {broker}")
print(f"{'='*60}\n")
else:
print("No boats were successfully retrieved.")Get comprehensive details of a boat listed on yachtr.com. Accepts either a full yachtr.com listing URL or the numeric vessel ID (the digits at the end of the URL). Returns specifications, engine info, description, full details, image URLs, and broker contact information.
| Param | Type | Description |
|---|---|---|
| boat_idrequired | string | Either a full yachtr.com boat listing URL (e.g. https://yachtr.com/44-ted_brewer-1995-2850869/) or the numeric vessel ID from the end of the URL (e.g. 2850869). |
{
"type": "object",
"fields": {
"title": "string",
"broker": "object with broker name, email, brokerage, and office_email",
"images": "array of image URLs",
"engines": "array of engine objects with make, model, type, horsepower, etc.",
"location": "string",
"boat_name": "string",
"price_usd": "string",
"vessel_id": "string",
"description": "string",
"full_details": "string",
"specifications": "object containing key-value pairs of boat specs (Name, LOA, Year, Beam, etc.)"
},
"sample": {
"title": "1995 Ted Brewer 44'",
"broker": {
"name": "John Doe",
"email": "[email protected]",
"brokerage": "David Walters Yachts",
"office_email": "[email protected]"
},
"images": [
"https://cdn.yachtbroker.org/images/2850869_9b4bbffd_1.jpg.webp"
],
"engines": [
{
"name": "Engine 1",
"Hours": "2300.00",
"Power HP": "72.00",
"Fuel Type": "Diesel",
"Engine Make": "Detroit Diesel",
"Engine Type": "Inboard",
"Engine Model": "3-53"
}
],
"location": "St. George's, Grenada",
"boat_name": "Victory 1995 Ted Brewer 44 ft Cutter by John Doe",
"price_usd": "-1169000",
"vessel_id": "2850869",
"description": "Custom Ted Brewer Design #98 - full-keel pilothouse offshore cutter built for serious bluewater cruising...",
"full_details": "Interior Accommodations and Layout...",
"specifications": {
"LOA": "43'10\" (13.36 Meters)",
"Beam": "13'6\"",
"Name": "Victory",
"Type": "Sail-Used",
"Year": "1995",
"Cabins": "2",
"Designer": "Ted Brewer",
"Fuel Type": "Diesel",
"Hull Material": "Fiberglass"
}
}
}About the Yachtr API
What the API Returns
The get_boat_details endpoint accepts a boat_id parameter that can be either a complete yachtr.com listing URL (e.g. https://yachtr.com/44-ted_brewer-1995-2850869/) or the numeric vessel ID at the end of that URL. The response includes the listing title, boat_name, vessel_id, price_usd, and location as top-level string fields, giving you the core identifiers and pricing data in one call.
Engine and Specification Data
The engines array returns one object per engine, each containing fields like make, model, type, and horsepower. This is particularly useful for filtering or comparing motorized vessels where engine configuration affects value. The description field holds the seller's narrative text, while full_details contains the structured specification block — typically covering dimensions, hull material, year, and other vessel attributes.
Images and Broker Contact
The images field returns an array of direct image URLs for the listing. The broker object surfaces the broker's name, email address, brokerage firm name, and office email, giving you everything needed to attribute a listing or route an inquiry without a separate contact lookup step.
The Yachtr API is a managed, monitored endpoint for yachtr.com — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when yachtr.com changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official yachtr.com API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Build a yacht comparison tool that pulls
full_detailsandenginesdata across multiple vessel IDs - Aggregate
price_usdandlocationfields to track regional pricing trends for used boats - Populate a CRM with broker contact records using the
brokerobject's name, email, and brokerage fields - Display listing galleries in a marine search product by consuming the
imagesarray - Monitor specific vessel IDs for price changes by periodically polling
get_boat_details - Feed boat inventory data into a financing calculator using
price_usdand engine horsepower fields - Qualify leads for marine brokerages by extracting
office_emailand broker name from listings
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 100 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
One credit = one API call regardless of which marketplace API you call. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does yachtr.com offer an official developer API?+
What exactly does the `broker` object contain?+
broker object returns four fields: broker (the individual broker's name), email (the broker's direct email), brokerage (the firm name), and office_email (the brokerage's general contact email). Not all listings have all four fields populated, depending on how the listing was submitted.Can I search or filter listings — for example, by boat type, price range, or location?+
get_boat_details; it does not expose a search or browse endpoint for filtering across the yachtr.com inventory. You can fork this API on Parse and revise it to add a search endpoint that accepts filter parameters.Does the API return sold or inactive listings?+
status field in the current response schema distinguishing active from sold listings. You can fork this API on Parse and revise it to add a listing status field if the source page exposes that information.Are multiple engines on a single vessel returned separately?+
engines field is an array, so twin-engine or multi-engine vessels will have one object per engine, each with its own make, model, type, and horsepower values.