# Facebook Events Scraper - Search by City or Page, No Login (`hyperbach/facebook-events-scraper`) Actor

Scrape Facebook events by keyword and city, page or event link: name, start and end time with the zone, place, address, city and coordinates, hosts, responded, going and interested counts, ticket link, full description, cover. No login, no cookies. Misses free.

- **URL**: https://apify.com/hyperbach/facebook-events-scraper.md
- **Developed by:** [Hyperbach](https://apify.com/hyperbach) (community)
- **Categories:** Social media, Lead generation, Automation
- **Features:** Limited permissions
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $6.50 / 1,000 events

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

## Facebook Events Scraper - Search by City or Page, No Login

**Facebook events as data, logged out.** Give words and a city ("comedy" in Chicago, or the leader's "Sport New York"), event links, page links, search links or a city alone, and get **one row per event**: the name, the start and end time with the **event's own zone and offset**, the place with its address, city, country and coordinates, the hosts (and whether each is a page), the responded total with the **going and interested counts apart** where Facebook shows them, the ticket link, the **whole description** with its links, the 960-px cover and a recurring event's dates. A free date window, a city-only cut, in-person or online, and no charge for an empty search. No login, no cookies, no browser, proxies handled for you.

**$13.00 per 1,000 `event` rows on the Free plan, $10.00 on Starter.** A run start is $0.004. The default input returns about 31 rows for about $0.394. A search with no result, an event id with no event, a page with no events and a place Facebook does not name are free rows that say so: you never pay for an input that gave no event.

![A Facebook event page in a browser: an invented night market with its cover photo, its date line, its venue, its host and how many people are interested and going. Beside it, the row this Actor returns for the event, with startTimeLocal (the start in the event's own time zone) and utcOffset highlighted, then the zone label, the start in UTC, the going and interested counts, the address and the host line.](https://api.apify.com/v2/key-value-stores/dcLLNGq99686o2A4v/records/hero-facebook-events-scraper.webp)

### Tested head-to-head on 2026-11-06

The job: the events of one Facebook search, 'Sport New York' (the schema's example and the leader's default input), 30 events with their full records. Every Actor ran on it the same day from the same harness; a rival's cost is what a buyer account paid, this Actor's is its list price on the Free plan. Fields counts the filled fields of a typical row. Facebook gives a search a different list on each connection, so the three lists are not the same events. Re-measured monthly.

| Actor | Rows | First row | Run time | Cost | Fields | Failures |
|---|---|---|---|---|---|---|
| **this Actor** | 22 | 30 s | 67 s | $0.29 | 41 | none |
| `apify/facebook-events-scraper` | 30 | 15 s | 53 s | $0.30 | 29 | none |
| `scrapegeist/facebook-organizer-events-scraper` | 30 | 40 s | 196 s | $0.12 | 29 | none |

### Why this Facebook events scraper

- **The place is Facebook's own place filter, read from the place's country.** "Sport New York" as one text lists 1 event on Facebook's search; the same words with New York as Facebook's place filter list 50 (step 304, the same connection and minute). This Actor splits the place out of your words, finds its location id, and reads the list from a connection in the place's country: a London search read from a UK connection listed 39 events where a US one listed 10.
- **Times you can use.** Every row has the start in UTC, the start in the event's own local time with its offset (`-05:00`), the zone label Facebook shows (`EST`, `UTC+05:30`) and the end time where the host set one. The offset comes from the event's own date line, never from the connection's or your zone.
- **Going and interested apart, and honest about rounding.** `usersResponded` is Facebook's exact total; `usersGoing` and `usersInterested` come apart from the event's own line ("538 interested and 49 going"), exact under 1,000; above 1,000 Facebook rounds them ("18K … 1.4K") and the row says `countsRounded` true. Facebook shows the split only above about a hundred answers (6 of 200 rows of our Chicago test, 116 to 436 answers); under it the two are empty, never a made-up 0.
- **No charge for an empty search.** A search with no result, a missing event, a page with no Events section or a place Facebook does not name is one free row with Facebook's own answer, checked on a second connection before it says `not_found`. Only delivered events are charged.
- **The whole list, not the first screen.** A search is read page by page to Facebook's own end of the list (16 events a call), a page's events to its count (49 of 49 on our test page), a city's events feed to its end; every input's free row says COMPLETE, CAPPED, DATE_LIMIT, SHORT_LIST or PARTIAL with how many events were listed.
- **Speed, measured on Apify** (build 0.1.12, 512 MB, 2026-11-06): 50 events of the search "comedy", each with its full record, in 39.8 to 74.3 seconds over three runs (the first event after 11.7 to 33.6 s; the lane leader took 62.8 s at 1,024 MB); 300 events of "music" in New York in 160 seconds; one event of "Sport New York" in 15.3 to 24.2 seconds; the default input (22 events, the list's end that minute) in 66.7 seconds, the first after 27.3 s. Facebook refuses many event-record calls on Apify's own connections and the event then waits for another connection: that sets the first event's time. The events of a list are read 8 at a time while the next page is read.
- **The details buyers ask for.** The hosts with their links (and `isPage`: a page or a person), the place's street, city, country and coordinates, Facebook's city id (`cityPageId`), the ticket link with its seller, the categories, the online and canceled flags, the description's own links, the 960-px cover (not the 64-px card), and each date of a recurring event.

### Who it's for

- **Event marketers and promoters** — every upcoming event in a city for a genre (`searchQueries` with a `location`), with the venue, the ticket link and the going and interested counts, to plan dates and watch the competition.
- **Venues, ticketing and travel teams** — the calendar of a list of venue or organizer pages (`startUrls`), upcoming and past, with each event's time, place, tickets and attendance, for listings or a sales pipeline.
- **Researchers and data teams** — a city's events feed or a set of searches inside a date window, with exact times, places and coordinates, for a dataset or a map.

### Quick start

**Comedy events in Chicago, the next 30 days**

```json
{
  "searchQueries": [
    "comedy"
  ],
  "location": "Chicago",
  "dateFrom": "today",
  "dateTo": "30 days",
  "maxEvents": 50
}
```

**The lane leader's form: words and a city in one line**

```json
{
  "searchQueries": [
    "Sport New York"
  ],
  "maxEvents": 30
}
```

**A venue's upcoming events**

```json
{
  "startUrls": [
    "https://www.facebook.com/ChicagoImprov"
  ],
  "maxEvents": 50
}
```

### Switching from `apify/facebook-events-scraper`?

Your input works as it is. Each name in the left column is read as this Actor's own field and the run log says so (`read <theirs> as <ours>`); a name marked *not read* is ignored with a note. A value in the other Actor's shape, an object list or its own date form, is read too.

| apify/facebook-events-scraper | this Actor | what to know |
|---|---|---|
| `searchQueries` | `searchQueries` | The same name and shape: one search a line, the words and the place together ("Sport New York") or the words alone with `location`. |
| `startUrls` | `startUrls` | The same name: event links, search links (with their place and date filters) and explore links, as strings or `{"url": …}` items; page links read the page's events. |
| `maxEvents` | `maxEvents` | The same name: the most events per search or link; empty = no limit. |

**What differs:**

- The leader's one-line form "Sport New York" works: the place is split out and sent as Facebook's own place filter, so the list is the city's (the leader's run of that input delivered 1 event; this Actor's lists 50). A `location` field sets the place for every search.
- The columns keep the leader's names (`utcStartDate`, `location`, `organizators`, `usersGoing`, `usersInterested`, `ticketsInfo`, `childEvents`, …); new ones sit beside them (`utcEndDate`, `startTimeLocal`, `utcOffset`, `cityPageId`, `countsRounded`, `isPage` on each host).
- The leader's always-empty flags (`paidContent`, `isClassEvent`, `isLiveAudioRoom`, `isRemoteLearningClass`, `isRemoteLearningCourse`, `groupEventPinnedToFeatured`, `hasRecordingAvailable`) and `privacyInfo` are not columns here.
- Each input gets a free summary row (`record_type` = `target`) beside its event rows; filter on `record_type` = `event` for the events alone.
- An empty search is a free row here, never a charged item.

### Output

One row per event (and one free summary row for every input):

| field | meaning |
|---|---|
| `record_type` | `event` on an event row (charged); `target` on an input's free summary row. |
| `status` | `ok`, or why an input gave no row: `no_results`, `not_found`, `no_events`, `place_not_found`, `invalid_input`, `duplicate`, `failed`, `not_read` (the FAQ says which is which). |
| `input` | The value you gave that this row answers: the search words, the link or the place. |
| `inputUrl` | The input as a Facebook link (the leader's `inputUrl`): the search link with its place filter, the event's, the page's or the explore link. |
| `id` | Facebook's id of the event (the leader's `id`). |
| `url` | The event's link, `https://www.facebook.com/events/<id>/` (the leader's `url`). |
| `name` | The event's name (the leader's `name`). |
| `utcStartDate` | The start in UTC, ISO 8601 (the leader's `utcStartDate`). |
| `utcEndDate` | The end in UTC where the host set one; empty when Facebook has none. |
| `startTimeLocal` | The start in the event's own local time with its offset (`2026-11-06T18:00:00-05:00`). |
| `endTimeLocal` | The end in the event's own local time with its offset, where the host set an end. |
| `timezone` | The zone label Facebook shows for the event (`EST`, `CET`, `UTC+05:30`). |
| `utcOffset` | The event's offset from UTC (`-05:00`), read from the event's own date line; empty when the event has no zone of its own (Facebook's `UNK`: some online events), and then `startTimeLocal` is empty and the date filter reads the UTC date. |
| `startTimestamp` | The start as Unix seconds. |
| `dateTimeSentence` | Facebook's own date line for the event, in the event's zone (the leader's `dateTimeSentence`; its style follows the connection: US or UK). |
| `startTime` | Facebook's short start line (`Thu, Nov 12 at 7:00 PM CST`; the leader's `startTime`). |
| `duration` | Facebook's duration line where it shows one (`5 hr 45 min`, `2 days`; the leader's `duration`). |
| `isPast` | True when the event has ended (the leader's `isPast`). |
| `isCanceled` | True when the host canceled the event (the leader's `isCanceled`). |
| `isOnline` | True for an online event (the leader's `isOnline`). |
| `eventType` | The event's kind: `PUBLIC` for a public event (the leader's `eventType`). |
| `location` | The place (the leader's `location`): `id`, `name`, `contextualName`, `placeType` (PLACE, CITY, TEXT …), `latitude`, `longitude`, `streetAddress`, `city`, `cityName` (Facebook's city page name), `countryCode` (from the place's own city and address, never the connection), `url`. |
| `address` | The place's one-line address where Facebook shows one. |
| `cityPageId` | Facebook's id of the event's city (its location id): the key of `strictCity`. |
| `organizedBy` | Facebook's "Event by …" line (the leader's `organizedBy`). |
| `organizators` | The hosts as Facebook publishes them with the event (the leader's `organizators`): `id`, `name`, `url`, `isVerified`, and `isPage` (true: a Facebook page; false: not shown as a page, a person's profile most often; empty: not read). |
| `usersResponded` | Facebook's exact count of people who answered going or interested (the leader's `usersResponded`); empty where the event shows no count (10 of 200 rows of our Chicago test: the host hides it). |
| `usersGoing` | People going (the leader's `usersGoing`): exact under 1,000, Facebook's rounded figure above (`countsRounded`); the responded total less interested when Facebook's line names interested only; empty where Facebook shows no split. |
| `usersInterested` | People interested (the leader's `usersInterested`): the responded total less going when going is exact (also when Facebook rounds interested), Facebook's rounded figure when both are rounded; empty where Facebook shows no split. A city feed's own line fills the split where the event page shows none. |
| `countsRounded` | True when a figure of the split stays Facebook's rounded one ("18K"); empty when it showed no split. |
| `ticketsInfo` | The ticket link (the leader's `ticketsInfo`): `buyUrl`, `title`, `subtitle` (the seller, "via TicketWeb"). |
| `description` | The event's whole description (the leader's `description`). |
| `externalLinks` | The web links in the description, as written (the leader's `externalLinks`, without the link shim). |
| `discoveryCategories` | Facebook's categories for the event (`label`, `url`; the leader's `discoveryCategories`); empty where Facebook files none. |
| `imageUrl` | The cover image, the 960-px rendition (the leader's `imageUrl`); a signed link that stops working after some days. |
| `imageWidth` | The original cover's width in pixels. |
| `imageHeight` | The original cover's height in pixels. |
| `imageCaption` | Facebook's text for the cover (the leader's `imageCaption`). |
| `eventFrequency` | `SINGLE`, or how a recurring event repeats (`WEEKLY`, `CUSTOM`; the leader's `eventFrequency`). |
| `hasChildEvents` | True for a recurring event with dates of its own (the leader's `hasChildEvents`). |
| `childEventsCount` | Facebook's count of the recurring event's dates. |
| `childEvents` | Each date of a recurring event (the leader's `childEvents`): `id`, `url`, `utcStartDate`, `utcEndDate`, `isPast`; read date by date from the upcoming dates on, up to the count or 12 more event reads (a long series: the row's `note` says how many of the count were read). |
| `parentEventId` | For one date of a recurring event: the id of the event it belongs to. |
| `searchPlace` | The place a search or city read, by Facebook's own name ("London, United Kingdom"). |
| `listCountry` | The country of the connection the list was read from (Facebook's search follows it; the Actor reads a place from its own country). |
| `detailsRead` | True when the event's full record was read; false for a list's own row (`eventDetails` false; a row a filter needs whole is read whole). |
| `verdict` | On an input row: COMPLETE, CAPPED, DATE_LIMIT, FILTER_BUDGET, SHORT_LIST or PARTIAL (the FAQ says which is which). |
| `rows_delivered` | On an input row: the events it delivered. |
| `note` | On an input row: what was read and why it stopped (the place, the country of the list, events listed, left out by each filter). On an event row: a part not read (the going / interested line). |
| `scraped_at` | When this row was read (UTC). |

Example record:

```json
{
  "record_type": "event",
  "status": "ok",
  "input": "party",
  "inputUrl": "https://www.facebook.com/events/search/?q=party&filters=eyJycF9ldmVudHNfbG9jYXRpb246MCI6IntcIm5hbWVcIjpcImZpbHRlcl9ldmVudHNfbG9jYXRpb25cIixcImFyZ3NcIjpcIjEwODY1OTI0MjQ5ODE1NVwifSJ9",
  "id": "2763833253983203",
  "url": "https://www.facebook.com/events/2763833253983203/",
  "name": "BERT KREISCHER: PERMISSION TO PARTY",
  "utcStartDate": "2026-11-07T01:00:00.000Z",
  "utcEndDate": null,
  "startTimeLocal": "2026-11-06T19:00:00-06:00",
  "endTimeLocal": null,
  "timezone": "CST",
  "utcOffset": "-06:00",
  "startTimestamp": 1794013200,
  "dateTimeSentence": "Friday, November 6, 2026 at 7:00 PM CST",
  "startTime": "Fri, Nov 6 at 7:00 PM CST",
  "duration": null,
  "isPast": false,
  "isCanceled": false,
  "isOnline": false,
  "eventType": "PUBLIC",
  "location": {
    "id": "1415869483908775",
    "name": "The Chicago Theatre",
    "contextualName": "The Chicago Theatre",
    "placeType": "TEXT",
    "latitude": 41.885262067801,
    "longitude": -87.627611090175,
    "streetAddress": null,
    "city": "Chicago",
    "cityName": "Chicago, Illinois",
    "countryCode": "US",
    "url": null
  },
  "address": "6 E Benton Pl, Chicago, IL 60601, United States",
  "cityPageId": "108659242498155",
  "organizedBy": "Event by Jam Productions, The Chicago Theatre and 2 others",
  "organizators": [
    {
      "id": "100064572108641",
      "name": "Jam Productions",
      "url": "https://www.facebook.com/jamusa",
      "isVerified": false,
      "isPage": true
    },
    {
      "id": "100064368176863",
      "name": "The Chicago Theatre",
      "url": "https://www.facebook.com/chicagotheatre",
      "isVerified": true,
      "isPage": true
    },
    {
      "id": "100044551384375",
      "name": "Bert Kreischer",
      "url": "https://www.facebook.com/BertKreischer",
      "isVerified": true,
      "isPage": true
    },
    {
      "id": "100044305005330",
      "name": "Outback Presents",
      "url": "https://www.facebook.com/OutbackPresents",
      "isVerified": true,
      "isPage": true
    }
  ],
  "usersResponded": 436,
  "usersGoing": 34,
  "usersInterested": 402,
  "countsRounded": false,
  "ticketsInfo": {
    "buyUrl": "https://ticketmaster.evyy.net/c/253158/264167/4272?u=https%3A%2F%2Fwww.ticketmaster.com%2Fbert-kreischer-permission-to-party-chicago-illinois-11-06-2026%2Fevent%2F0700647FBB075CC2&utm_medium=affiliate",
    "title": "Tickets",
    "subtitle": "via Ticketmaster"
  },
  "description": "PLEASE NOTE: Pricing is all-in and includes fees (before taxes if applicable). By purchasing tickets to this event, you agree to abide by the health and safety measures in effect a …(truncated for display)",
  "externalLinks": [
    "http://www.chicagotheatre.com/"
  ],
  "discoveryCategories": [
    {
      "label": "Comedy",
      "url": "https://www.facebook.com/events/search/?filters=eyJmaWx0ZXJfZXZlbnRzX2NhdGVnb3J5OjAiOiJ7XCJuYW1lXCI6XCJmaWx0ZXJfZXZlbnRzX2NhdGVnb3J5XCIsXCJhcmdzXCI6XCIyMTA0MTIxMTM5ODUwMTAwXCJ9In0%3D&q=Comedy"
    }
  ],
  "imageUrl": "https://scontent-lax3-1.xx.fbcdn.net/v/t39.99422-6/719742153_1855294592315655_148067568928535877_n.png?stp=dst-jpg_tt6",
  "imageWidth": 1200,
  "imageHeight": 628,
  "imageCaption": "May be an image of text",
  "eventFrequency": "SINGLE",
  "hasChildEvents": false,
  "childEventsCount": 0,
  "childEvents": [],
  "parentEventId": null,
  "searchPlace": "Chicago, Illinois",
  "listCountry": "US",
  "detailsRead": true,
  "verdict": null,
  "rows_delivered": null,
  "note": null,
  "scraped_at": "2026-11-06T08:53:31Z"
}
```

### Pricing

**Pay for the events a run delivers**, plus one run start; no platform usage and no proxy traffic is billed to you. The event price falls with your Apify plan.

| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
| Event (`event`) | per 1,000 | $13.00 | $10.00 | $8.50 | $6.50 |
| Run start (`start`) | per run | $0.004 | $0.004 | $0.004 | $0.004 |

An event is **$13.00 per 1,000** on the Free plan ($0.013 an event) and $10.00 on Starter, with its full record (the times, the place, the hosts, the counts, the tickets, the description, the cover and a recurring event's dates): there is no add-on. Each run that delivers a charged event also pays the **run start, $0.004 once**; a run that delivers no charged event pays nothing at all. So the default input's 30 events cost $0.394 on the Free plan and $0.304 on Starter; 100 events $1.304 and $1.004; 1,000 events $13.004 and $10.004; every input of a run shares one start. The free `target` row of every input, a search with no result (`no_results`), an event id with no event (`not_found`), a page with no events (`no_events`), a place Facebook does not name (`place_not_found`), a value that is not a Facebook link (`invalid_input`), a repeated input (`duplicate`), an event a filter leaves out (the dates, `strictCity`, `eventFormat`, `excludeCanceled`), an input left at a cap or the time limit (`not_read`) and a refusal the run could not pass (`failed`) are never charged. An event is charged once a run, also when several inputs list it. A run that stops early (a timeout, an abort) is charged for the events it delivered.

Before the first request the log names the price of an event at your plan, the run start and the most the run can cost: `maxEvents` for each input, `maxItems` over the whole run, and never more than your charge limit. With no cap a list is read to Facebook's own end: in our tests a search listed 1 to 321+ events ("music" in New York: 321 over 18 pages, no end), a page's upcoming tab 49, a past tab's count 2,184 (300 read in a test), New York's city feed 406+. With `eventDetails` off and a filter on (the dates, `strictCity`, `eventFormat`, `excludeCanceled`), each listed event the filter needs is read in full first, so the run takes the details' time (one test read 80 events for the 20 it delivered, in 206 seconds); only the delivered events are charged. Enterprise plans have their own rates — the Actor's Pricing tab shows the price for your plan.

### Usage patterns

- **Searches, places and the date window** — Each line of `searchQueries` is one search. With `location` (a city name, Facebook's location id or an explore link) every search reads that place; without it, a place at the end of the words is split out ("jazz London", "yoga Austin TX"), and words that are only a place ("Paris") read that city's events feed. A name several towns carry is read as the first one Facebook's place index lists ("Manchester" was read as a US Manchester in our test): each row's `searchPlace` names the place read; give Facebook's location id or the explore link for another one. Facebook's place filter is the city's metro area: `strictCity` keeps the events whose own city is the asked one (dropped events are free). `dateFrom` / `dateTo` take a date (`2026-12-01`) or a span from today (`7 days`); they go to Facebook as its own date filter and are checked again on each event's local date. Facebook's search and city feed list upcoming events only. Facebook answers a search with a different list on each connection, and at some hours most connections get only a short list (on one test, 2 of 12 connections gave the full list): a short first page is read on up to 12 more connections at once, and an input that still got a short list says `SHORT_LIST`.
- **Pages, events and limits** — A page link reads the page's events: `pageEvents` picks upcoming (the default), past (newest first) or both; a link to `/past_hosted_events/` reads the past ones. An event link (or its bare id) reads that event; a recurring event's dates come in `childEvents`. `maxEvents` caps each input, `maxItems` the whole run; both are checked before an event is read, so no event past them is read or charged. `eventDetails` false gives the lists' own rows only (faster: the name and link; a page's and a city's rows also carry the start and the place, a city's the counts).
- **What a row is** — `record_type` = `event`: one event, charged. `record_type` = `target`: one free row per input with its `status`, `verdict`, `rows_delivered`, the place read and the country of the connection the list came from, and a `note` that says what was read and why it stopped. An event two inputs list is delivered once, for the first. The cover link is Facebook's own and stops working after some days: download what you keep.

### Input configuration

| field | type | default | what it does |
|---|---|---|---|
| `searchQueries` | `array` | `[]` | One search a line: words like 'jazz' or 'comedy', read in the place of 'Location' below. With no location, a place at the end of the words is split out and searched as Facebook's own place filter ('Sport New York' = 'Sport' in New York; a US state code is read too: 'yoga Austin TX'). Words that are only a place ('New York') read that city's events feed. Facebook's search lists upcoming events only. |
| `location` | `string` |  | The city every search above reads: a name ('Chicago', 'London', 'Austin TX'), Facebook's location id (108659242498155) or an explore link (https://www.facebook.com/events/explore/us-chicago/108659242498155/). Facebook's place filter is the city's metro area; turn on 'This city only' to keep the city's own events. With no search words and no links, the city's events feed is read. A name several towns carry is read as the first one Facebook's place index lists ('Manchester' was read as a US Manchester in our test): each row's searchPlace names the place read; give the location id for another. |
| `startUrls` | `array` | `[]` | One link a line. An event (https://www.facebook.com/events/1152191060472061/, or the bare id): that event. A page (https://www.facebook.com/ChicagoImprov, /ChicagoImprov/upcoming_hosted_events, /past_hosted_events, /people/<name>/<id>/, profile.php?id=…): the page's events. A search link (https://www.facebook.com/events/search/?q=comedy\&filters=…): its words, place and dates. An explore link (/events/explore/us-chicago/108659242498155/): the city's events feed. A group's link is not read in this version; it gets a free row that says so. |
| `maxEvents` | `integer` |  | The most events to deliver from each search, page or city. Empty = no limit: the list is read to its own end. |
| `maxItems` | `integer` | `0` | The most charged events of the whole run; 0 = no cap beyond your charge limit. |
| `dateFrom` | `string` |  | Only events that start on this day or later, by the date where the event happens: 2026-12-01, or a span from today (7 days). Sent to Facebook as its own date filter and checked again on every event. An event outside the dates is not delivered and not charged. |
| `dateTo` | `string` |  | Only events that start on this day or earlier: 2026-12-31, or a span from today (30 days). |
| `strictCity` | `boolean` | `false` | Facebook's place filter is the city's metro area (about half of a city's list is in the suburbs). On: keep only the events whose own city is the asked place. The suburbs' events are not delivered and not charged. |
| `eventFormat` | `any` / `in_person` / `online` | `"any"` | Keep every event, only the events at a place, or only the online events. |
| `excludeCanceled` | `boolean` | `false` | On: a canceled event is not delivered and not charged. |
| `pageEvents` | `upcoming` / `past` / `both` | `"upcoming"` | For page links: the upcoming events, the past events (newest first), or both. A page link to /past_hosted_events/ reads the past ones whatever this says. Searches and cities list upcoming events only. |
| `eventDetails` | `boolean` | `true` | On (default): every row carries the event's full record. Off: the list's own row only, faster: the name and link (a search), plus the start and the place (a page or a city), plus the counts (a city). Event links are always read in full. With a date window, eventFormat, excludeCanceled or strictCity, a list row that lacks the field the filter reads (a search's row has no date, no online flag and no city) is read in full, so the filter holds. |
| `secondView` | `boolean` | `true` | Facebook's search answers a different list on each connection (our test: one search ended at 12 to 127+ events on five connections in the same minute). On (default): a search whose list ends is read again on up to two fresh connections, and their new events are added, until one adds none. You pay only for the events delivered; it costs the time of the extra reads. Off: one connection's list. |
| `proxyUrl` | `string` |  | Your own proxy (scheme://user:pass@host:port) for every call instead of ours. Leave empty: the Actor brings its own connections at no cost to you. |
| `feedback` | `string` |  | A note to the people who maintain this Actor: what you needed and did not get. For example a missing field, a wrong or empty result, or the Actor you switch from or to, and why. The run does not read it: the rows and the charges stay the same. A person reads every note. |

### Errors

**A run does not fail because of your input.** When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends **Succeeded**, charges nothing, and says what to change:

- the status message starts with `INPUT REJECTED`;
- the dataset holds one row, `{"error": true, "code": "…", "message": "…"}`, and no results;
- the key-value store record `ERROR` holds the same object.

From code, check `error` on the first row before reading results.

A search with no result, an event that does not exist, a page with no Events section, a place Facebook's explore pages do not name, or a value that is not a Facebook link is not an error: it gets one free row with its `status` and the reason, and the run goes on with the others. A run that ends **Failed** is a fault on our side, never your input; it charges nothing, and we are alerted.

### FAQ

**Which status and verdict is which?**

An event row is `ok`. An input row: `ok` with a verdict (`COMPLETE`: read to Facebook's own end of the list; `CAPPED`: maxEvents reached; `DATE_LIMIT`: an ordered list passed your dates; `FILTER_BUDGET`: your filters matched too few of the events read; `SHORT_LIST`: Facebook's search answered only a short list on every one of up to 13 connections read, which it does on most connections at some hours: run it again later; `PARTIAL`: stopped early, the note says why), or free: `no_results` (Facebook's search lists no event for the words and place, on two connections), `not_found` (no event or page by that link, two connections agree), `no_events` (the page has no Events section or lists none), `place_not_found` (Facebook's explore pages name no such place: give its location id or explore link), `invalid_input` (not a Facebook link this Actor reads), `duplicate` (another form of an input already given: read once), `failed` (Facebook refused every connection tried; run it again later), `not_read` (maxItems, your charge limit or the time limit came first). Searches, city feeds and a page's upcoming tab deliver upcoming events only: a past event Facebook still lists there is left out, free, and the note counts it.

**Why are some events outside the city I asked?**

Facebook's place filter is the city's metro area: about half of a big city's list is in its suburbs (our measure: 32 of 57 events of a New York list in New York's own city page, all within 72 km). Every row carries the event's own city, country and `cityPageId`; turn on `strictCity` to keep the asked city's own events, free for the rest.

**Why are going and interested sometimes empty?**

Facebook shows the going / interested line only above about a hundred answers (our Chicago test: 6 of 200 events, 116 to 436 answers); under it only the total is shown, and that is in `usersResponded`. Above 1,000 Facebook rounds the two (18K, 1.4K) and the row says `countsRounded` true.

**Can it read group events or the guest list?**

Not in this version: a group's link gets a free row that says so. The guest list (who is going) is never read: the counts only.

**Does it need a Facebook account, cookies or an API key?**

No. Everything is read from Facebook's public, logged-out answers: no login, no cookie, no token of yours. The connections are included in the price.

### Integration

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/facebook-events-scraper').call({"searchQueries": ["comedy"], "location": "Chicago", "dateFrom": "today", "dateTo": "30 days", "maxEvents": 50});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/facebook-events-scraper').call(run_input={'searchQueries': ['comedy'], 'location': 'Chicago', 'dateFrom': 'today', 'dateTo': '30 days', 'maxEvents': 50})
items = client.dataset(run['defaultDatasetId']).list_items().items
```

#### CLI

```bash
apify call hyperbach/facebook-events-scraper --input '{"searchQueries": ["comedy"], "location": "Chicago", "dateFrom": "today", "dateTo": "30 days", "maxEvents": 50}'
```

#### REST

```bash
curl -X POST "https://api.apify.com/v2/acts/hyperbach~facebook-events-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' -d '{"searchQueries": ["comedy"], "location": "Chicago", "dateFrom": "today", "dateTo": "30 days", "maxEvents": 50}'
```

#### AI agents and MCP

Apify's MCP server offers this Actor as a tool to Claude, Cursor, VS Code and any other MCP client. Connect `https://mcp.apify.com?tools=hyperbach/facebook-events-scraper` and ask, for example: "Find upcoming comedy events in Chicago on Facebook with their dates, venues, ticket links and going counts". The agent fills the input from the table above and reads the rows from the run's dataset. A field under the name another Actor gives it is read as this Actor's own: `queries`, `searchTerms`, `keywords`, `search` as `searchQueries`; `urls`, `url`, `links`, `eventUrls` as `startUrls`; `locationId`, `searchLocation`, `location_uid`, `city` as `location`; `maxResults`, `maxEventsPerQuery`, `resultsLimit`, `limit` as `maxEvents` (and more). An agent or a person can add `feedback` to any run and say what was needed and not delivered: a missing field, a wrong or empty result, the Actor switched from or to, and why. The run returns the same rows at the same price, and a person reads every note.

#### n8n, Make and Zapier

The Apify node in n8n, the Apify app in Make and the Apify integration in Zapier run this Actor on a schedule or from a trigger and read its dataset. A webhook on the run's end (Integrations on the Actor page) sends the rows on to your own endpoint. Nothing to install on our side.

### Support

**Disagree with a charge?** Write to apify@hyperbach.com with the run ID. We will ask Apify to compensate you, and the charge comes back to your Apify account as platform credit.

**Did it do the job?** A short [review on the Store](https://apify.com/hyperbach/facebook-events-scraper/reviews), at any rating, helps the next buyer choose.

### See also

- **[Meta Ad Library Scraper](https://apify.com/hyperbach/meta-ads-library-scraper)** — every ad a page runs on Facebook, Instagram, Messenger, WhatsApp and Threads, with the landing URL, media, run dates and EU reach.
- **[Threads Scraper](https://apify.com/hyperbach/threads-scraper)** — Threads profiles with the exact follower count, their posts and replies with view counts, and keyword and tag search, without a login.
- **[Instagram Reels Transcript Scraper](https://apify.com/hyperbach/instagram-reels-transcript-scraper)** — the spoken words of Instagram reels, by reel link or creator, with the exact posting time.
- **[Instagram Posts Scraper](https://apify.com/hyperbach/instagram-posts-scraper)** — the posts and reels of Instagram profiles, with the whole caption, the exact publish time, likes, comments and plays.
- **[Instagram Hashtag Scraper](https://apify.com/hyperbach/instagram-hashtag-scraper)** — Instagram's own ranked list of top reels for a hashtag or a search keyword.
- **[Facebook Pages Scraper](https://apify.com/hyperbach/facebook-pages-scraper)** — Facebook pages by URL, id, name or search words: the exact follower count, categories, address, phone, e-mail and websites, and the page transparency facts.

*This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.*

# Actor input Schema

## `searchQueries` (type: `array`):

One search a line: words like 'jazz' or 'comedy', read in the place of 'Location' below. With no location, a place at the end of the words is split out and searched as Facebook's own place filter ('Sport New York' = 'Sport' in New York; a US state code is read too: 'yoga Austin TX'). Words that are only a place ('New York') read that city's events feed. Facebook's search lists upcoming events only.

## `location` (type: `string`):

The city every search above reads: a name ('Chicago', 'London', 'Austin TX'), Facebook's location id (108659242498155) or an explore link (https://www.facebook.com/events/explore/us-chicago/108659242498155/). Facebook's place filter is the city's metro area; turn on 'This city only' to keep the city's own events. With no search words and no links, the city's events feed is read. A name several towns carry is read as the first one Facebook's place index lists ('Manchester' was read as a US Manchester in our test): each row's searchPlace names the place read; give the location id for another.

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

One link a line. An event (https://www.facebook.com/events/1152191060472061/, or the bare id): that event. A page (https://www.facebook.com/ChicagoImprov, /ChicagoImprov/upcoming_hosted_events, /past_hosted_events, /people/<name>/<id>/, profile.php?id=…): the page's events. A search link (https://www.facebook.com/events/search/?q=comedy\&filters=…): its words, place and dates. An explore link (/events/explore/us-chicago/108659242498155/): the city's events feed. A group's link is not read in this version; it gets a free row that says so.

## `maxEvents` (type: `integer`):

The most events to deliver from each search, page or city. Empty = no limit: the list is read to its own end.

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

The most charged events of the whole run; 0 = no cap beyond your charge limit.

## `dateFrom` (type: `string`):

Only events that start on this day or later, by the date where the event happens: 2026-12-01, or a span from today (7 days). Sent to Facebook as its own date filter and checked again on every event. An event outside the dates is not delivered and not charged.

## `dateTo` (type: `string`):

Only events that start on this day or earlier: 2026-12-31, or a span from today (30 days).

## `strictCity` (type: `boolean`):

Facebook's place filter is the city's metro area (about half of a city's list is in the suburbs). On: keep only the events whose own city is the asked place. The suburbs' events are not delivered and not charged.

## `eventFormat` (type: `string`):

Keep every event, only the events at a place, or only the online events.

## `excludeCanceled` (type: `boolean`):

On: a canceled event is not delivered and not charged.

## `pageEvents` (type: `string`):

For page links: the upcoming events, the past events (newest first), or both. A page link to /past_hosted_events/ reads the past ones whatever this says. Searches and cities list upcoming events only.

## `eventDetails` (type: `boolean`):

On (default): every row carries the event's full record. Off: the list's own row only, faster: the name and link (a search), plus the start and the place (a page or a city), plus the counts (a city). Event links are always read in full. With a date window, eventFormat, excludeCanceled or strictCity, a list row that lacks the field the filter reads (a search's row has no date, no online flag and no city) is read in full, so the filter holds.

## `secondView` (type: `boolean`):

Facebook's search answers a different list on each connection (our test: one search ended at 12 to 127+ events on five connections in the same minute). On (default): a search whose list ends is read again on up to two fresh connections, and their new events are added, until one adds none. You pay only for the events delivered; it costs the time of the extra reads. Off: one connection's list.

## `proxyUrl` (type: `string`):

Your own proxy (scheme://user:pass@host:port) for every call instead of ours. Leave empty: the Actor brings its own connections at no cost to you.

## `feedback` (type: `string`):

A note to the people who maintain this Actor: what you needed and did not get. For example a missing field, a wrong or empty result, or the Actor you switch from or to, and why. The run does not read it: the rows and the charges stay the same. A person reads every note.

## Actor input object example

```json
{
  "searchQueries": [
    "Sport New York"
  ],
  "startUrls": [],
  "maxEvents": 30,
  "maxItems": 0,
  "strictCity": false,
  "eventFormat": "any",
  "excludeCanceled": false,
  "pageEvents": "upcoming",
  "eventDetails": true,
  "secondView": true
}
```

# Actor output Schema

## `results` (type: `string`):

All scraped records in the default dataset. One row per event (and one free summary row for every input):

## `runSummary` (type: `string`):

How the run went: events charged, free rows by status, each input's verdict, events listed and pages read, the country each list was read from, the source counters (requests and seconds by call, connections opened, refused and dead, bytes), the first and last row's seconds and the memory watch.

# 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 = {
    "searchQueries": [
        "Sport New York"
    ],
    "maxEvents": 30
};

// Run the Actor and wait for it to finish
const run = await client.actor("hyperbach/facebook-events-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 = {
    "searchQueries": ["Sport New York"],
    "maxEvents": 30,
}

# Run the Actor and wait for it to finish
run = client.actor("hyperbach/facebook-events-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 '{
  "searchQueries": [
    "Sport New York"
  ],
  "maxEvents": 30
}' |
apify call hyperbach/facebook-events-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hyperbach/facebook-events-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/q9B7u0eA5PzE8F6Gn/builds/3zxBj13hNjVlSVb3g/openapi.json
