# CozyCozy Scraper (`crawlerbros/cozycozy-scraper`) Actor

Scrape lodging listings from CozyCozy's public catalog pages - hotels, vacation rentals, hostels, apartments, and more, across 13 English-language markets, with price, rating, review count, geo-coordinates, and address.

- **URL**: https://apify.com/crawlerbros/cozycozy-scraper.md
- **Developed by:** [Crawler Bros](https://apify.com/crawlerbros) (community)
- **Categories:** Travel, Real estate, Lead generation
- **Stats:** 3 total users, 2 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/actors/running/actors-in-store.md#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

## CozyCozy Scraper

Scrape lodging listings from [CozyCozy](https://www.cozycozy.com) — a hotel and vacation-rental price-comparison / metasearch engine similar to HomeToGo and Trivago. Browse by city or country and accommodation type, or fetch specific CozyCozy catalog URLs directly. No login, no cookies, no paid proxy required.

### What this actor does

- **Two modes:** browse by location + accommodation type, or fetch specific CozyCozy catalog URLs
- **17 accommodation types:** hotels, vacation rentals, apartments, serviced apartments, villas, resorts, motels, cabins, hostels, short-term rentals, B\&Bs, cottages, lodges, holiday parks, chalets, unique stays, and general lodging
- **13 English-language markets:** US, UK, Canada, Australia, Ireland, New Zealand, South Africa, Singapore, Hong Kong, India, Philippines, UAE, Indonesia — each with its own local currency
- **Rich per-listing data:** price, rating (0-10 scale), review count, star rating, address, GPS coordinates, description, and photo
- **Filters:** minimum rating, minimum official star rating, maximum price per night, minimum review count, keyword search, and strict accommodation-type matching
- **Empty fields are omitted** — every record only contains data CozyCozy actually returned

### Output per listing

- `title` — property name
- `accommodationType` — CozyCozy's own type label for this listing (e.g. `hotel`, `motel`, `aparthotel`)
- `ratingScore` — 0-10 guest rating (when CozyCozy shows one)
- `reviewCount` — number of reviews behind that rating
- `starRating` — official star rating (1-5), when available
- `priceFromAmount`, `priceCurrency` — "from" price per night and its ISO currency code
- `priceValidFrom` — date the shown price quote is valid from
- `imageUrl` — listing photo
- `bookingProvider` — which booking platform this specific rate/card came from (e.g. `Booking.com`, `Expedia`, `Airbnb`, `Agoda`), when identifiable from the listing photo's source. CozyCozy is a metasearch engine, so the same physical property can appear multiple times on one page — once per platform it aggregates rates from, each with its own price/rating — this field lets you tell those apart.
- `description` — property description
- `landmarkDistance` — distance/context text (e.g. "0.5 miles from Eiffel Tower")
- `address` — `{ streetAddress, locality, postalCode }`, when available
- `latitude`, `longitude` — GPS coordinates, when available
- `searchLocation`, `searchAccommodationType`, `market` — the input that produced this record
- `sourceUrl` — the CozyCozy catalog page this listing was found on
- `recordType: "listing"`, `scrapedAt`

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| `mode` | string | `byLocation` | `byLocation` or `byUrl` |
| `locations` | array | `["Paris"]` | City or country names (mode=byLocation) |
| `accommodationType` | select | `hotels` | One of 17 lodging types (mode=byLocation) |
| `market` | select | `us` | One of 13 English-language markets (mode=byLocation) |
| `startUrls` | array | – | Direct CozyCozy catalog URLs (mode=byUrl) |
| `minRating` | number | – | Drop listings rated below this (0-10 guest-review scale) |
| `minStarRating` | integer | – | Drop listings whose official star rating (0-5) is below this — distinct from `minRating` |
| `maxPricePerNight` | number | – | Drop listings priced above this (local currency) |
| `minReviews` | integer | – | Drop listings with fewer reviews than this |
| `strictTypeMatch` | boolean | `false` | Drop off-type fallback listings CozyCozy shows when a city has no exact matches |
| `containsKeyword` | string | – | Only keep listings whose title/description contains this text |
| `maxItems` | integer | `50` | Hard cap on emitted records |
| `proxyConfiguration` | object | Apify proxy (fallback only) | Optional; the actor tries a direct connection first |

### Example input

```json
{
  "mode": "byLocation",
  "locations": ["Paris", "Tokyo", "New York"],
  "accommodationType": "hotels",
  "market": "us",
  "minRating": 7,
  "maxItems": 100
}
```

```json
{
  "mode": "byUrl",
  "startUrls": [
    { "url": "https://www.cozycozy.com/us/paris-hotels" },
    { "url": "https://www.cozycozy.com/gb/london-apartments" }
  ]
}
```

### Use cases

- **Price comparison research** — track "from" prices across cities and accommodation types
- **Market analysis** — compare hotel vs. vacation-rental pricing and ratings in a destination
- **Travel content** — pull curated, rated lodging lists for a city guide or itinerary tool
- **Lead generation** — find highly-rated independent hotels/B\&Bs in a target market

### FAQs

**Does this need a CozyCozy account or API key?**
No. It scrapes CozyCozy's public, search-engine-indexed catalog pages.

**How many listings can I get per location?**
Each catalog page returns up to ~40 listings server-rendered by CozyCozy. Add more locations/types to widen coverage.

**What happens if a location has no listings of the requested type?**
CozyCozy shows other nearby lodging as a fallback. Enable `strictTypeMatch` to drop those and keep only exact-type matches.

**Why only English-language markets?**
Non-English CozyCozy markets (e.g. `/fr/`, `/de/`) use localized location slugs that don't match a plain English city name, so they're out of scope for reliable automatic URL-building in `byLocation` mode. You can still reach any market's page directly via `byUrl` mode if you already know the exact URL.

**Why do I sometimes see the same property name more than once for one location?**
CozyCozy is a metasearch/price-comparison engine — the same physical property can appear as multiple separate cards, one per booking partner (Booking.com, Expedia, Hotels.com, etc.), each with its own `priceFromAmount`, `ratingScore`, and `reviewCount`. These are not duplicate scrapes; they're genuinely different rate offers for the same address, exactly as CozyCozy's own page displays them.

### Limitations

- Individual accommodation detail pages and CozyCozy's internal `/api` and `/*/search` endpoints are disallowed by `robots.txt` and are never fetched by this actor — output is limited to fields shown on the public catalog page.
- CozyCozy's catalog pages don't expose further pagination beyond the first server-rendered batch (~40 listings) per location/type combination.

# Actor input Schema

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

What to fetch.

## `locations` (type: `array`):

City or country names to search, e.g. `Paris`, `New York`, `Tokyo`, `Germany`. One catalog page is fetched per location.

## `accommodationType` (type: `string`):

Type of lodging to browse for each location.

## `market` (type: `string`):

Which localized CozyCozy site to browse (affects currency and result ranking). Only English-language markets are supported.

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

Direct CozyCozy catalog page URLs, e.g. `https://www.cozycozy.com/us/paris-hotels`. Enter one URL per row in the Console (it wraps each into `{"url": "..."}` automatically); via the API, send an array of `{"url": "..."}` objects.

## `minRating` (type: `number`):

Drop listings with a review score below this value (CozyCozy uses a 0-10 scale). Listings with no rating shown still pass through.

## `minStarRating` (type: `integer`):

Drop listings whose official star rating (e.g. a "4-star hotel") is below this value. Distinct from `minRating`, which is the guest review score. Listings with no official star rating shown still pass through.

## `maxPricePerNight` (type: `number`):

Drop listings whose "from" price per night is above this value, in the market's local currency.

## `minReviews` (type: `integer`):

Drop listings with fewer reviews than this.

## `strictTypeMatch` (type: `boolean`):

When a city has no listings of the requested type, CozyCozy shows other nearby options instead. Enable this to drop those off-type fallback listings and keep only ones matching the requested type.

## `containsKeyword` (type: `string`):

Only keep listings whose title or description contains this text (case-insensitive).

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

Hard cap on emitted records across all locations/URLs. Each catalog page typically yields up to ~40 listings.

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

Optional. CozyCozy's catalog pages load fine from a direct connection; the actor tries direct first and only engages this free Apify datacenter proxy as a fallback if a page gets blocked or rate-limited.

## Actor input object example

```json
{
  "mode": "byLocation",
  "locations": [
    "Paris"
  ],
  "accommodationType": "hotels",
  "market": "us",
  "startUrls": [],
  "strictTypeMatch": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `listings` (type: `string`):

Dataset containing all scraped CozyCozy lodging 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": "byLocation",
    "locations": [
        "Paris"
    ],
    "accommodationType": "hotels",
    "market": "us",
    "startUrls": [],
    "strictTypeMatch": false,
    "maxItems": 50,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("crawlerbros/cozycozy-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": "byLocation",
    "locations": ["Paris"],
    "accommodationType": "hotels",
    "market": "us",
    "startUrls": [],
    "strictTypeMatch": False,
    "maxItems": 50,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("crawlerbros/cozycozy-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": "byLocation",
  "locations": [
    "Paris"
  ],
  "accommodationType": "hotels",
  "market": "us",
  "startUrls": [],
  "strictTypeMatch": false,
  "maxItems": 50,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call crawlerbros/cozycozy-scraper --silent --output-dataset

```

## MCP server setup

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