# Giggster Scraper \[$1.50/1K💰] | Venue & Studio Rental Data (`ahmed_jasarevic/giggster-scraper`) Actor

Scrape venue and space rentals from Giggster across US, UK and Canada - hourly rate, capacity, square footage, features, amenities, house rules, catering, photos, host, availability and FAQs.

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

## Pricing

from $1.30 / 1,000 venues

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

## Giggster Scraper

Scrape **venue and space rentals** from [Giggster](https://giggster.com) across the US, UK and Canada — hourly rate, capacity by event type, square footage, features, amenities, house rules, catering options, insurance and alcohol conditions, photos, host profile, availability and FAQs. Built for venue marketplaces, event-industry research, pricing benchmarks and commercial property directories.

Two collection modes: a **fast search-API sweep** and a **full detail** pass over 14,000+ venues.

### What you get

#### Capacity broken out by event type, not one vague number

Most venue listings publish a single "capacity" figure that is meaningless. Giggster publishes them separately, and the Actor keeps them separate:

| Field | Meaning |
| --- | --- |
| `capacity.maxAttendees` | **Resolved** headline figure |
| `capacity.maxAttendeesProduction` | Production/filming capacity |
| `capacity.maxAttendeesEvent` | General event capacity |
| `capacity.maxAttendeesMeeting` | Seated-meeting capacity |
| `capacity.maxAttendeesPlay` | Rehearsal/play capacity |
| `capacity.castAndCrew` | Cast and crew headcount |
| `capacity.sittingLimit` / `standingLimit` | Seated vs standing limits |
| `capacity.parkingCapacity` | On-site parking spaces |
| `capacity.crewAccess` | Crew access notes |

`capacity.maxAttendees` is **computed** from the others in order — event → production → meeting → play → castAndCrew — so you always have a usable headline number without losing the specific one you actually need. The difference between a 200-capacity production space and a 200-capacity meeting room is exactly what makes a venue bookable or not.

#### Rate card, not just one number

`hourlyRate` is the base hourly figure, but `priceLevels` preserves the **whole ladder** Giggster publishes (any `price-*` property), plus `minimumHours`. A venue charging £18/hr base may quote £2,400 for a weekend; `priceLevels` is where that lives, and `minimumHours` is what tells you whether a 3-hour booking is even possible.

#### The rules that actually disqualify a venue

This is what separates a real venue dataset from a photo scrape. You get, as separate arrays:

- `rules`, `rulesNotAllowed`, `additionalRules` — house rules, in both directions
- `cateringOptions`, `cateringNotAllowed` — catering policy
- `insuranceRequired` — public liability insurance requirement
- `alcoholLicenceConditions` — licensing constraints
- `specialRequirements`, `restrictedAreas` — load-in, noise, access restrictions
- `instantBook` — instant-booking conditions

Combined with `features`, `amenities`, `activities`, `propertySizeBuckets` and `tags`, you can answer "which venues in this city allow a 60-person sit-down dinner with external catering, have parking, and don't require insurance" — a query that is impossible against flat listing data.

#### Host profiles with verification signals

`host` carries `name`, `firstName`, `lastName`, `role`, `responseRate`, `isSuperhost`, `memberSince`, `avatarUrl`, `profileUrl` and a `verified` object with **`email`, `phone` and `google` verification flags**.

Those verification flags are the useful part: `verified.phone: true` tells you the listed number is confirmed, which matters for event planners booking on someone else's behalf. `acceptanceRate`, `bookingsCount`, `commentsCount` and `ratingCount` tell you whether a venue is reliably bookable or just theoretically listed.

#### Availability you can plan against

`availability` carries `calendarFrom`, `calendarTo`, `bookableFrom` and `blockedDates[]`. Not a full calendar, but enough to know a venue's booking window and which dates are already out — which is frequently the reason a booking falls through.

#### Location, privacy-aware

`location` gives `address`, `suite`, `neighborhood`, `city`, `state`, `zipcode`, `country`, `fullAddress`, `latitude`, `longitude`, `timezoneOffset`, `processingRegion` — plus two flags that matter: **`addressBlurred`** and **`geoBlurred`**. When Giggster blurs a location until payment, the Actor preserves that instead of guessing, so you never record a precise address the platform deliberately withheld.

### How it works

Giggster's site search runs on its **own public JSON endpoint**, so the Actor can collect venue data without scraping HTML:

| Purpose | Endpoint | Notes |
| --- | --- | --- |
| Venue search | `api.giggster.com/locations/ft-search` | 100 rows/page, offset paging, **no auth, no special headers** |
| Venue detail | `giggster.com/listing/{slug}` | Full 51-field record |
| Full catalogue | `giggster.com/sitemap-listings.xml` | 14,000+ venues, **one request** |
| City list | `giggster.com` active-cities blob | Resolves `placeSlug` → city/country |

#### Two ways in

**`searchUrls`** — you paste a normal Giggster search URL such as `https://giggster.com/search/Manchester--UK/production`. The Actor parses out the place slug and activity, resolves the city against Giggster's active-cities list, and translates it into `ft-search` API calls. Because it's the API, not HTML, you get clean JSON and offset pagination instead of a rendered page.

**`searchUrls: []`** — the Actor falls back to `sitemap-listings.xml` and crawls the **entire 14,000+ venue catalogue** from a single request. That's the mode you want for a full inventory.

#### `includeDetails` is where the cost difference lives

With `includeDetails: true` (default) every discovered venue gets its `/listing/{slug}` page parsed into the full record. With `includeDetails: false`, the `ft-search` API item is mapped **directly into the identical row shape** and detail pages are never opened — one page of 100 rows costs one request.

The row shape is the same either way. Fields the search index doesn't carry (square footage, amenities, rules, reviews, availability, FAQ) come back `null` or empty rather than being guessed. So a cheap run is a valid, uniformly-shaped dataset — just shallower.

#### Advanced: raw API enrichment

A hidden `enrichWithApi` input (not shown in the Console form, but accepted via the API) additionally fetches `api.giggster.com/locations/{id}` for each venue and attaches the raw record under the **`api`** key. This adds machine-readable `properties` and `tags` that the page parser can't derive. It **doubles request count**, so use it for targeted enrichment rather than a full sweep.

#### Cost control

A free/paid gate caps the venue budget: free accounts are limited to **10 venues** and the run stops there, so a free run never queues thousands of detail pages. `maxRequestsPerCrawl` can be set explicitly, or left empty for an automatic value derived from `maxListings`.

### Input

| Field | Type | Default | Notes |
| --- | --- | --- | --- |
| `searchUrls` | string\[] | `["https://giggster.com/search/Manchester--UK/production"]` | Giggster search URLs (place + activity), translated into `ft-search` API calls. Empty = full catalogue from the sitemap. |
| `maxListings` | integer | `200` | Max venues (1–15,000), shared across all search URLs. |
| `includeDetails` | boolean | `true` | Scrape `/listing/{slug}` detail pages. `false` returns search-API rows only — much faster. |
| `maxRequestsPerCrawl` | integer | auto | Hard cap on total HTTP requests. Leave empty for a value derived from `maxListings`. |
| `proxy` | object | `{ "useApifyProxy": false }` | Standard Apify proxy picker. |
| `enrichWithApi` | boolean | `false` | **Advanced, API-only** (not in the Console form). Fetches the raw `api.giggster.com/locations/{id}` record into the `api` key. Doubles requests. |

Leave `searchUrls` empty for the whole catalogue:

```json
{ "searchUrls": [], "maxListings": 5000, "includeDetails": true }
```

### Output

One flat dataset. Every record has `dataType: "listing"`.

**51 top-level fields**, grouped:

| Group | Fields |
| --- | --- |
| Identity | `dataType`, `id`, `slug`, `url`, `name`, `venueType`, `primaryType`, `description`, `status` |
| Pricing | `hourlyRate`, `currency`, `priceLevels`, `minimumHours` |
| Physical | `capacity` (object), `squareFootage`, `squareMeters`, `propertyDetails`, `dimensions` |
| Amenities | `features`, `amenities`, `activities`, `propertySizeBuckets`, `tags` |
| Rules | `rules`, `rulesNotAllowed`, `additionalRules`, `cateringOptions`, `cateringNotAllowed`, `insuranceRequired`, `alcoholLicenceConditions`, `specialRequirements`, `restrictedAreas`, `instantBook` |
| Media | `photos`, `photosCount`, `mapImageUrl`, `seoImage` |
| Location | `location` (object) |
| Host | `host` (object or null) |
| Reputation | `rating`, `ratingCount`, `acceptanceRate`, `reviews`, `reviewsCount`, `commentsCount`, `bookingsCount` |
| Availability | `availability` (object or null) |
| Extras | `addons`, `faq`, `scrapedAt`, `api` |

#### Nested objects — read these, don't look for flat fields

`capacity` and `location` are **objects**. So `city` is `location.city`, not `city`; `maxAttendees` is `capacity.maxAttendees`, not `maxAttendees`.

```json
"capacity": {
  "maxAttendees": 200,
  "maxAttendeesProduction": 200,
  "maxAttendeesEvent": 150,
  "maxAttendeesMeeting": 80,
  "maxAttendeesPlay": null,
  "castAndCrew": 25,
  "sittingLimit": null,
  "standingLimit": null,
  "parkingCapacity": 40,
  "crewAccess": []
}
```

```json
"location": {
  "address": "12 Dale Street",
  "suite": null,
  "neighborhood": "Northern Quarter",
  "city": "Manchester",
  "state": "England",
  "zipcode": "M1 1FY",
  "country": "United Kingdom",
  "fullAddress": "12 Dale Street, Manchester M1 1FY",
  "addressBlurred": false,
  "latitude": 53.4813,
  "longitude": -2.2331,
  "geoBlurred": false,
  "timezoneOffset": 0,
  "processingRegion": "eu-west-2"
}
```

`host` is `null` when not published. `availability` is `null` when not published. `api` is populated **only** when `enrichWithApi: true`.

Field notes that change how you read the data:

- With `includeDetails: false`, `squareFootage`, `squareMeters`, `features`, `amenities`, `rules`, `reviews`, `availability`, `addons` and `faq` are `null`/`[]`. That is **missing data, not empty data** — distinguish it in your pipeline.
- `photos[]` entries carry `url`, `width` and `height`. `photosCount` is Giggster's own count and can differ from `photos.length`.
- `addressBlurred` / `geoBlurred` are privacy flags, not errors. Respect them.
- `capacity.maxAttendees` is **derived** by the Actor from the typed capacities. If you need to know which underlying figure produced it, read the typed fields.
- `priceLevels` keys are Giggster's own `price-*` property names, not friendly labels.
- `ratingCount` vs `reviewsCount` vs `commentsCount` are three different counts. Don't merge them.

### Example input

Fast search-API sweep, no detail pages:

```json
{
  "searchUrls": ["https://giggster.com/search/Manchester--UK/production"],
  "includeDetails": false,
  "maxListings": 300
}
```

Multiple cities and activities, full detail:

```json
{
  "searchUrls": [
    "https://giggster.com/search/London--UK/wedding",
    "https://giggster.com/search/New-York--US/conference",
    "https://giggster.com/search/Toronto--CA/meetings"
  ],
  "includeDetails": true,
  "maxListings": 750
}
```

Whole-catalogue inventory:

```json
{
  "searchUrls": [],
  "maxListings": 5000,
  "includeDetails": true,
  "maxRequestsPerCrawl": 6000
}
```

Raw API enrichment for hard-to-parse fields:

```json
{
  "searchUrls": ["https://giggster.com/search/Bristol--UK/production"],
  "maxListings": 50,
  "includeDetails": true,
  "enrichWithApi": true
}
```

### Example output

```json
{
  "dataType": "listing",
  "id": "5f8a3c2b91d4e70012",
  "slug": "the-warehouse-studios-manchester",
  "url": "https://giggster.com/listing/the-warehouse-studios-manchester",
  "name": "The Warehouse Studios",
  "venueType": "Studio",
  "primaryType": "production",
  "description": "A 4,500 sq ft former warehouse in the Northern Quarter, licensed for events and production. Concrete floors, 3-phase power, blackout windows and on-site loading.",
  "status": "active",
  "hourlyRate": 65,
  "currency": "GBP",
  "priceLevels": { "price-base-hourly": 65, "price-day": 1040, "price-week": 7280 },
  "minimumHours": 4,
  "capacity": {
    "maxAttendees": 200,
    "maxAttendeesProduction": 200,
    "maxAttendeesEvent": 200,
    "maxAttendeesMeeting": 80,
    "maxAttendeesPlay": null,
    "castAndCrew": 25,
    "sittingLimit": null,
    "standingLimit": null,
    "parkingCapacity": 40,
    "crewAccess": []
  },
  "squareFootage": 4500,
  "squareMeters": 418,
  "propertyDetails": [{ "label": "Year built", "value": "1924" }],
  "dimensions": [{ "label": "Main hall", "value": "120 x 60 ft" }],
  "features": ["Blackout windows", "3-phase power", "Loading dock", "Green room"],
  "amenities": ["WiFi", "Heating", "Toilets", "Accessible entrance"],
  "activities": ["Production", "Photography", "Corporate events"],
  "propertySizeBuckets": ["2500-5000 sqft"],
  "tags": ["warehouse", "industrial", "daylight"],
  "rules": ["No smoking", "Load-in via rear entrance only"],
  "rulesNotAllowed": ["Open flame", "Confetti"],
  "additionalRules": ["Curfew of 02:00 for amplified sound"],
  "cateringOptions": ["External catering allowed", "On-site kitchen"],
  "cateringNotAllowed": [],
  "insuranceRequired": true,
  "alcoholLicenceConditions": ["Venue holds a licence to 02:00", "Personal licence required after 00:00"],
  "specialRequirements": ["Public liability insurance of £5m minimum"],
  "restrictedAreas": ["Second-floor office not accessible during events"],
  "instantBook": [],
  "photos": [{ "url": "https://cdn.giggster.com/photos/warehouse-01.jpg", "width": 2048, "height": 1365 }],
  "photosCount": 24,
  "mapImageUrl": null,
  "seoImage": "https://cdn.giggster.com/photos/warehouse-01.jpg",
  "location": {
    "address": "12 Dale Street",
    "suite": null,
    "neighborhood": "Northern Quarter",
    "city": "Manchester",
    "state": "England",
    "zipcode": "M1 1FY",
    "country": "United Kingdom",
    "fullAddress": "12 Dale Street, Manchester M1 1FY",
    "addressBlurred": false,
    "latitude": 53.4813,
    "longitude": -2.2331,
    "geoBlurred": false,
    "timezoneOffset": 0,
    "processingRegion": "eu-west-2"
  },
  "host": {
    "id": "usr_2c9f11",
    "name": "Rachel T.",
    "firstName": "Rachel",
    "lastName": "T.",
    "role": "Owner",
    "responseRate": 1,
    "isSuperhost": true,
    "avatarUrl": "https://cdn.giggster.com/avatars/usr_2c9f11.jpg",
    "memberSince": "2019-04",
    "verified": { "email": true, "phone": true, "google": true },
    "profileUrl": "https://giggster.com/users/usr_2c9f11"
  },
  "rating": 4.92,
  "ratingCount": 47,
  "acceptanceRate": 0.98,
  "reviews": [],
  "reviewsCount": 47,
  "commentsCount": 132,
  "bookingsCount": 289,
  "availability": {
    "calendarFrom": "2026-08-01",
    "calendarTo": "2027-07-31",
    "bookableFrom": "2026-10-15",
    "blockedDates": ["2026-12-24", "2026-12-25"]
  },
  "addons": [
    { "name": "House PA", "category": "Staffing", "price": 320, "priceUnit": "day", "description": null },
    { "name": "Projector hire", "category": "Equipment", "price": 45, "priceUnit": "day", "description": null }
  ],
  "faq": [
    { "q": "Is there parking?", "a": "Yes, 40 spaces on site, free after 6pm." }
  ],
  "scrapedAt": "2026-10-04T06:12:41.220Z",
  "api": null
}
```

### Integrations & automation

Call it over the Apify API (`POST /v2/acts/ugJhOSfeKYansvx9Q/runs`), or from Python, JavaScript, the CLI or MCP. Output exports as JSON, CSV, Excel, XML or RSS.

For **pricing benchmarks**, run `includeDetails: false` across many cities to build a cheap rate-card index (`hourlyRate`, `priceLevels`, `capacity`, `location.city`), then re-run detail only on the outliers you want to analyse. For **venue discovery**, filter `features`, `amenities` and `rulesNotAllowed` — "allows external catering, has parking, no insurance requirement" is a rules-level query. For **host reliability**, filter `host.isSuperhost`, `host.responseRate` and `acceptanceRate` before shortlisting.

Typical pipeline: run on schedule → flatten `location` and `capacity` into columns → explode `features`/`amenities` into a bridge table → upsert on `id` → alert when `hourlyRate` or `availability.bookableFrom` changes. Because venue data changes slowly, weekly runs are usually enough; use daily only for `blockedDates` in high-demand markets.

#### What a run costs

| Configuration | Billable events | Cost |
| --- | --- | --- |
| 200 venues, `includeDetails: false` | 200 × Venue | **$0.30** |
| 200 venues, with details | 200 Venue + 200 Venue-detail | **$0.70** |
| 5,000 venues, `includeDetails: false` | 5,000 × Venue | **$7.50** |

Two event types: **$0.0015 per venue** and **$0.002 per venue detail**. Detail rows cost about 33% more, so `includeDetails: false` is the main cost lever. Free accounts are capped at **10 venues**. Paid accounts get the full `maxListings` range up to 15,000, with tiered rates on higher plans.

### Related Actors

| Actor | Why |
| --- | --- |
| [`peerspace-scraper`](https://apify.com/ahmed_jasarevic/peerspace-scraper) | The closest comparison in this portfolio — same venue-rental problem, different marketplace. |
| [`tagvenue-scraper`](https://apify.com/ahmed_jasarevic/tagvenue-scraper) | UK event-space data, directly complementary for UK venue coverage. |
| [`venuederby-scraper`](https://apify.com/ahmed_jasarevic/venuederby-scraper) | Another venue marketplace for cross-platform availability and rate comparison. |
| [`google-maps-scraper`](https://apify.com/ahmed_jasarevic/google-maps-scraper) | Geospatial venue discovery to seed which cities and categories to target. |
| [`yellowpages-ca-scraper`](https://apify.com/ahmed_jasarevic/yellowpages-ca-scraper) | Business directory data for enriching venue and host records. |

### FAQ

#### How do I crawl all 14,000+ venues?

Leave `searchUrls` empty. The Actor falls back to `giggster.com/sitemap-listings.xml` — **one request** — and works through the whole catalogue. Set `maxListings` up to 15,000 and give yourself `maxRequestsPerCrawl` headroom (detail mode costs roughly one request per venue).

#### What's the difference between `includeDetails: true` and `false`?

`false` maps the `ft-search` API row **directly into the identical record shape** and never opens a detail page — so a 100-row page costs one request. `true` fetches each `/listing/{slug}` page for square footage, amenities, rules, reviews, availability and FAQ. Both produce the same shape; with `false` the detail-only fields are `null`/`[]`. It also costs ~33% more per venue.

#### Why is `city` null when the venue clearly has an address?

Because `city` lives inside `location`, not at the top level — and with `includeDetails: false` the search index doesn't always carry it. Read `location.city`. If it's still null, that's a search-index gap, not a parse failure.

#### Should I filter on `addressBlurred`?

If you're building a public directory, yes. When Giggster blurs an address until payment, `addressBlurred: true` means the platform deliberately withheld the exact location. The Actor preserves that rather than inferring it — don't try to reconstruct it.

#### What does `capacity.maxAttendees` actually mean?

It's **derived** by the Actor, taking the first available value from `maxAttendeesEvent`, `maxAttendeesProduction`, `maxAttendeesMeeting`, `maxAttendeesPlay`, then `castAndCrew`. If you need to know *why* a venue is 200-capable, read the typed fields — the derived number alone hides that distinction.

#### What's the `enrichWithApi` input, and why isn't it in the form?

It's a hidden advanced input accepted via the API (not exposed in the Console UI). It fetches the raw `api.giggster.com/locations/{id}` record into the `api` key, adding machine-readable `properties` and `tags` that the HTML parser can't derive. It **doubles request count**, so use it for targeted enrichment of a few dozen venues, not a full sweep.

#### Do I need a browser or proxy?

No. The Actor talks to Giggster's own public JSON API and its sitemap over plain HTTP — no JavaScript rendering, no browser, no captcha. `proxy` defaults to off.

#### Why is my free run limited to 10 venues?

Free accounts are deliberately capped at 10 venues, and the run stops there rather than queueing thousands of detail pages. That is a free-tier limit, not a scraping failure.

### SEO Keywords

giggster scraper, venue rental data, event space listings, studio rental database, filming location data, photo shoot venue, wedding venue data, conference room listings, hourly rate benchmarks, venue capacity data, space for rent, event venue api, coworking space data, venue search api, property rental listings, us uk canada venues, production studio rental, party venue finder, event industry research, venue marketplace data, hospitality listings, room hire data, commercial space listings, event planning data

### For AI Agents & LLM Apps

Returns Giggster venue listings as **one flat dataset, 51 top-level fields per record**, all with `dataType: "listing"`.

**Minimal input** — smallest valid run:

```json
{ "searchUrls": [] }
```

**Cheapest useful sweep** — search API only, no detail requests:

```json
{ "searchUrls": ["https://giggster.com/search/Manchester--UK/production"], "includeDetails": false, "maxListings": 300 }
```

**Full detail across cities**:

```json
{ "searchUrls": ["https://giggster.com/search/London--UK/wedding"], "includeDetails": true, "maxListings": 200 }
```

**Whole catalogue**:

```json
{ "searchUrls": [], "maxListings": 5000, "includeDetails": true }
```

**Output fields (51 top-level):** dataType, id, slug, url, name, venueType, primaryType, description, status, hourlyRate, currency, priceLevels, minimumHours, capacity, squareFootage, squareMeters, propertyDetails, dimensions, features, amenities, activities, propertySizeBuckets, tags, rules, rulesNotAllowed, additionalRules, cateringOptions, cateringNotAllowed, insuranceRequired, alcoholLicenceConditions, specialRequirements, restrictedAreas, instantBook, photos, photosCount, mapImageUrl, seoImage, location, host, rating, ratingCount, acceptanceRate, reviews, reviewsCount, commentsCount, bookingsCount, availability, addons, faq, scrapedAt, api

**`capacity` object (10):** maxAttendees, maxAttendeesProduction, maxAttendeesEvent, maxAttendeesMeeting, maxAttendeesPlay, castAndCrew, sittingLimit, standingLimit, parkingCapacity, crewAccess

**`location` object (14):** address, suite, neighborhood, city, state, zipcode, country, fullAddress, addressBlurred, latitude, longitude, geoBlurred, timezoneOffset, processingRegion

**`host` object (12, or null):** id, name, firstName, lastName, role, responseRate, isSuperhost, avatarUrl, memberSince, verified (email/phone/google), profileUrl

**`availability` object (4, or null):** calendarFrom, calendarTo, bookableFrom, blockedDates

**Behaviours an agent should know**

- **`capacity` and `location` are nested objects.** `city` is `location.city`; `maxAttendees` is `capacity.maxAttendees`. Flat paths like `record.city` return undefined. Flatten explicitly before filtering.
- **`capacity.maxAttendees` is derived** by the Actor from `maxAttendeesEvent` → `maxAttendeesProduction` → `maxAttendeesMeeting` → `maxAttendeesPlay` → `castAndCrew`. Read the typed fields if you need the specific capacity.
- **`includeDetails: false` yields null detail-only fields** — `squareFootage`, `squareMeters`, `features`, `amenities`, `activities`, `rules`, `reviews`, `availability`, `addons`, `faq`. The record shape is identical, so treat missing as "not collected", not "empty".
- **Two billing event types:** $0.0015 per venue and $0.002 per venue detail. Detail mode costs ~33% more per venue, so `includeDetails: false` is the primary cost lever.
- **Free accounts are capped at 10 venues** and the run halts there. Paid accounts reach `maxListings` up to 15,000.
- **Empty `searchUrls` means "crawl everything"** — it falls back to `sitemap-listings.xml` (one request) and walks the full 14,000+ catalogue. This is the opposite of most Actors, where empty means no data.
- `enrichWithApi: true` is an **API-only hidden input** (not in the Console form). It populates the `api` key with the raw location record and **doubles request count**.
- `host` and `availability` are `null` when unpublished — always null-check.
- `addressBlurred` and `geoBlurred` are **privacy flags**, not errors. Don't reconstruct blurred locations.
- `photos[]` entries are `{ url, width, height }`; `photosCount` is Giggster's own count and may differ from `photos.length`.
- `ratingCount`, `reviewsCount` and `commentsCount` are three distinct counts — do not merge them.
- `priceLevels` keys are Giggster's internal `price-*` property names, not human-readable labels.
- No browser and no proxy are needed; both talk over plain HTTP to Giggster's public API and sitemap.

### Legal & Compliance

This Actor is an independent third-party tool. It is not affiliated with, endorsed by, or sponsored by Giggster, or by any venue host whose listing appears in its output.

**What it actually accesses:** Giggster's public venue search JSON endpoint at `api.giggster.com/locations/ft-search` (no authentication, no special headers required), the public venue detail pages at `giggster.com/listing/{slug}`, and the published `giggster.com/sitemap-listings.xml`. No login, no captcha solving, no browser, no header spoofing, no access-control bypass.

**robots.txt:** Giggster's `robots.txt` disallows `/unsupported`, `/unsupported-browser`, `/projects` and `/project-detail` — **none of which this Actor requests**. The paths used (`/search/*`, `/listing/*`, `/find/cities`, `/sitemap-listings.xml`) are permitted, and the sitemap is explicitly the discovery mechanism the platform publishes for exactly this purpose. `api.giggster.com` serves no `robots.txt`.

**Personal data.** Venue listings are commercial information, but the `host` object contains **identifiable personal data**: `name`, `firstName`, `lastName`, `avatarUrl`, `profileUrl`, `memberSince` and a `responseRate` tied to a specific account. Depending on where the host is based, **GDPR** (UK and EU venues, and the UK GDPR post-Brexit), **PIPEDA** (Canada) and **CCPA** (California venues) may all apply.

In particular: `verified.phone: true` confirms a phone number is associated with a real account, and that phone number is usable for contact. Do not treat verified contact details as consent to be marketed to. Under GDPR, host contact details collected for a booking purpose are **not** a marketing basis — you need separate consent or a legitimate-interest assessment, and you must give notice, honour erasure requests, and stop processing on objection. Do not build profiles of individual hosts.

**Commercial terms.** `robots.txt` permission is not a commercial licence. Giggster's Terms of Use reserve rights over its venue database, host profiles, reviews and images, and venue listings belong to the individual hosts who published them. **Building a competing venue marketplace or aggregator from this data without a licence is very likely to breach those terms**, even though every URL you request is publicly readable. If your intent is commercial reuse, get written permission from Giggster first — that is the durable route, not technical access.

**Photos and images.** Venue photos belong to the hosts and may carry third-party copyright. Do not republish them commercially without the relevant rights.

You are solely responsible for compliance with Giggster's Terms of Use, `robots.txt`, applicable data-protection law, and any permission you obtain. Keep volumes sensible — `maxRequestsPerCrawl` bounds a run without effort — and if you need venue data at commercial scale, licence it.

# Actor input Schema

## `searchUrls` (type: `array`):

Giggster search result URLs, e.g. `https://giggster.com/search/Manchester--UK/production` (place + activity). The Actor translates each URL into the public `api.giggster.com/locations/ft-search` API and collects the matching venues. Leave empty to crawl the full catalogue from `sitemap-listings.xml` (14,000+ venues).

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

Maximum number of venues to return, shared across all search URLs. Venue URLs come from the ft-search API (or `sitemap-listings.xml` when searchUrls is empty, where 14,000+ venues are available).

## `includeDetails` (type: `boolean`):

Scrape the venue detail pages (`/listing/…`) — pricing, capacity, amenities, rules, host, photos, location. Turn off for a fast run that returns rows straight from the search API without opening detail pages.

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

Hard safety cap on total HTTP requests. Leave empty for an automatic value derived from maxListings.

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

Select proxies to be used by your crawler.

## Actor input object example

```json
{
  "searchUrls": [
    "https://giggster.com/search/Manchester--UK/production"
  ],
  "maxListings": 200,
  "includeDetails": true,
  "proxy": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "searchUrls": [
        "https://giggster.com/search/Manchester--UK/production"
    ],
    "proxy": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("ahmed_jasarevic/giggster-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 = {
    "searchUrls": ["https://giggster.com/search/Manchester--UK/production"],
    "proxy": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("ahmed_jasarevic/giggster-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 '{
  "searchUrls": [
    "https://giggster.com/search/Manchester--UK/production"
  ],
  "proxy": {
    "useApifyProxy": false
  }
}' |
apify call ahmed_jasarevic/giggster-scraper --silent --output-dataset

```

## MCP server setup

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