# Facebook Events Scraper - $0.90 per 1,000 Events (`dami_studio/facebook-events-scraper`) Actor

Search public Facebook events by keyword, city, Page or Group and get every event in full: name, description, start and end time with timezone, venue address and GPS, organiser, tickets, cover image and going/interested counts. No login. The cheapest Facebook events scraper on the market.

- **URL**: https://apify.com/dami\_studio/facebook-events-scraper.md
- **Developed by:** [Dami's Studio](https://apify.com/dami_studio) (community)
- **Categories:** Social media, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.90 / 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.

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

## What's an Apify Actor?

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

## How to integrate an Actor?

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

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

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

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

# README

## Facebook Events Scraper

Type what you are looking for — "concert", "startup meetup", "food festival" — add a city if you want, or paste Facebook event, Page or Group URLs, and get public Facebook events back as clean, flat rows. Every row is the full event, not a search snippet: the whole description, the exact start and end time with its timezone, the venue with its street address and coordinates, the organising Page, the ticket link, the cover image and how many people are going or interested. No login, no cookies, no Facebook account, no browser, and nothing for you to configure.

- Search by keyword, by city, by Facebook Page, by Group, or straight from an event URL — mix them in one run.
- Full event detail on every row, including the complete description and the venue's street address and latitude/longitude.
- Going and interested counts, and the total number of people who have responded, wherever the host makes them public.
- Date windows, categories, online-only and ticketed-only are filters on the input, not paid add-ons — events they drop are never charged.
- A city name is matched against Facebook's own location list, so "Berlin" returns events in Berlin rather than events with "Berlin" in the title.
- Runs with empty input return a labelled sample row, free, so you can see the shape first.
- A private, deleted or misspelled event produces an uncharged diagnostic row, never a failed run.

### Price

**$0.90 per 1,000 events**, plus a **$0.001 start fee per run** (billed per gigabyte of run memory, so exactly that on the default 1 GB).

This is **the cheapest Facebook events scraper on the market**, and it is the same rate on every plan, free or paid. There are no volume tiers, no minimum spend, no subscription and no add-on fees. What you read here is what you pay on day one and on day four hundred.

| Events | Total cost |
|---|---|
| 100 | $0.091 |
| 1,000 | $0.901 |
| 10,000 | $9.001 |
| 100,000 | $90.001 |

#### What is actually charged

- **One `event-scraped` event per event row written to the dataset.** Nothing else is metered per row.
- **Free:** the sample row an empty run returns, and every diagnostic row — a blocked target, a dead URL, a search that matched nothing. Those rows all carry `"charged": false`.
- Events dropped by your date window, category, online-only or ticketed-only filters are never charged — the filters run before billing.
- Duplicate events found through more than one search term or URL are dropped before they are charged.
- Looking a city name up against Facebook's location list costs nothing.
- A search that matches nothing produces one free note row and no event charges.
- A run that finds nothing costs the start fee and nothing more.
- Rows never leave the dataset without a charge, and are never charged without a row. The billed event is a named one, so there is no price quietly attached to `apify-default-dataset-item` — the trick that makes some scrapers bill you for their own error messages.

### Input

```json
{
  "searchTerms": [
    "startup meetup",
    "tech conference"
  ],
  "location": "Berlin",
  "maxEvents": 20,
  "startingFrom": "2026-09-01",
  "startingBefore": "2026-12-31"
}
```

| Field | What it does |
|---|---|
| `searchTerms` | What to search Facebook events for. Up to 20 terms per run, each searched in turn. Facebook's public events search hands back up to 8 events per term, so several narrow terms beat one broad one. |
| `location` | A city name such as `Berlin`, or a Facebook events URL for a city (`https://www.facebook.com/events/explore/<city>/<id>/`) when you want an exact area. Applies to every search term in the run. |
| `startUrls` | Any mix of event URLs, Page URLs or handles, Group URLs, Facebook events search URLs and city explore URLs. Up to 50 per run. |
| `maxEvents` | Total events to return across everything above. Default 20. Keep it low while testing; you pay per event. |
| `startingFrom` | Optional, free. Drop events starting before this. Accepts `2026-09-01`, a full ISO timestamp, an epoch, or a relative window such as `7 days`. |
| `startingBefore` | Optional, free. Drop events starting after this. Same formats. |
| `category` | Optional, free. One of Facebook's own event categories — music, sports, comedy, theatre, art, food and the rest. |
| `onlineOnly` | Optional, free. Only events Facebook marks as online. |
| `paidOnly` | Optional, free. Only ticketed events. |
| `includePastEvents` | Optional, free. Off by default. Turn it on to also read a Page's or Group's past events. |
| `proxyUrls` | Leave empty. Fill it in only if you want the traffic to leave through proxy servers you already pay for, as `http://user:pass@host:port`. |

Run it with **empty input** and you get one clearly labelled sample row, free, so you can see the output shape before you spend anything.

### Output

One row per event. A real row from a real run:

```json
{
  "ok": true,
  "charged": true,
  "recordType": "event",
  "eventId": "1045755418043207",
  "eventUrl": "https://www.facebook.com/events/1045755418043207/",
  "name": "Devassas Concert",
  "description": "Rock concerts with Devassas (portuguese band - punk, grunge, metal) and Die Ausreden (powerpunk) at Regenbogenfabrik, in Berlin!\nSee ya!",
  "startTime": "2026-08-21T17:00:00.000Z",
  "startTimestamp": 1787331600,
  "endTime": null,
  "endTimestamp": null,
  "timezone": "UTC+02",
  "dateText": "Friday, August 21, 2026 at 7:00 PM CEST",
  "venueName": "Regenbogenfabrik",
  "venueAddress": "Lausitzer Straße 21a, 10999 Berlin, Germany",
  "venueCity": "Berlin, Germany",
  "venueUrl": "https://facebook.com/Regenbogenfabrik",
  "latitude": 52.495993170936,
  "longitude": 13.426580093814,
  "isOnline": false,
  "onlineUrl": null,
  "organizers": [
    {
      "id": "61580124287250",
      "name": "Devassas Band",
      "url": "https://www.facebook.com/people/Devassas-Band/61580124287250/",
      "type": "User"
    }
  ],
  "organizerName": "Devassas Band",
  "organizerUrl": "https://www.facebook.com/people/Devassas-Band/61580124287250/",
  "ticketUrl": null,
  "priceRange": null,
  "attendingCount": 4,
  "interestedCount": 2,
  "respondedCount": 6,
  "coverImageUrl": "https://scontent.xx.fbcdn.net/v/t39.30808-6/772604334_122136197643004142_4062119575631978264_n.jpg",
  "categories": [],
  "isCanceled": false,
  "isPast": false,
  "sourceType": "search",
  "sourceQuery": "concert",
  "sourceUrl": "https://www.facebook.com/events/search/?q=concert",
  "scrapedAt": "2026-08-16T13:39:24.434Z"
}
```

#### Field notes

- `eventId` — Facebook's own numeric id for the event — stable, and the thing to key on when you re-run and merge.
- `startTime` — the exact start in ISO 8601 UTC, read from the event itself rather than from a "Sat, 21 Aug" label. `startTimestamp` is the same moment in epoch seconds and `dateText` is the sentence Facebook prints.
- `endTime` — null when the host never set an end time, which is common. It is not an error and it is not guessed.
- `timezone` — the event's own timezone as Facebook stores it, so you can put a local start time back together from `startTimestamp`.
- `venueAddress` — the one-line address Facebook shows on the event. For an event whose "venue" is a free-text line rather than a Page, this and `venueName` can be the same string — that is what the host typed.
- `latitude / longitude` — the venue coordinates. Null for online events and for the small number of events whose host typed a place name Facebook could not resolve.
- `organizers` — every host Facebook lists, each with name, Page or profile URL, id and type. `organizerName` and `organizerUrl` repeat the first one so a spreadsheet has a plain column to sort on.
- `ticketUrl` — the external ticketing link the host attached. Null when tickets are not sold through a link, and `priceRange` carries the price band when Facebook shows one.
- `attendingCount / interestedCount` — the going and interested numbers as Facebook publishes them, which are rounded on large events ("1.2K interested" becomes 1200). `respondedCount` is the exact total where Facebook gives one. All three are null when the host hides the guest list.
- `sourceType / sourceQuery / sourceUrl` — how this event was found — `search`, `city`, `page`, `group` or `url` — so rows from a multi-term run can be grouped afterwards.

Every real row carries `"charged": true`. Sample rows carry `"_sample": true` and diagnostic rows carry `"_diagnostic": true` with an `errorCode` you can filter on, and neither is ever billed.

### How it works

- Facebook renders its public event pages, its public events search and a Page's hosted-events tab server-side, and this Actor reads those renders directly. No account is created, no cookies are planted and no login is ever attempted.
- The data is taken from the structured payload Facebook ships inside the page, not scraped out of on-screen text, so a start time is a real timestamp and a venue is a real place object with coordinates.
- Traffic leaves through a large pool of rotating addresses that cost nothing per gigabyte. If Facebook answers one address with a stub, the run takes a different address and asks again rather than giving up or charging you.
- Each page read stops as soon as the event data has arrived instead of downloading the rest of the render, which is what keeps the price where it is.
- You can point it at your own proxy servers instead, and nothing else changes.

### What people use it for

- Event aggregators and "what's on" sites filling a city listing without hand-entering anything.
- Venue and promoter research — who is putting on what, where, and how many people said they are coming.
- Sponsorship and sales teams building a pipeline of upcoming conferences, meetups and festivals in a territory.
- Local media and tourism boards monitoring what is happening in a city over a date window.
- Anyone tracking their own or a partner Page's event calendar into a spreadsheet or a database.

### Limitations

- Facebook's logged-out surfaces are shallow by design: one search term returns up to 8 events, one city page up to 12, and a Page or Group about 8. Going deeper needs a logged-in session, which this Actor will not use. Runs are therefore built to go WIDE — many terms, many cities, many Pages in one run — rather than deep on one term.
- Private events, events restricted to a Group's members, and events behind an age or country gate are not public. They come back as an uncharged diagnostic row rather than a partial one.
- The guest list itself is never public. `attendingCount`, `interestedCount` and `respondedCount` come from the counters Facebook prints on the event, they are rounded on large events, and they are null when the host hides them.
- `endTime` and `ticketUrl` are null whenever the host did not set them. That is most casual events, and no value is invented to fill the column.
- A city name is matched against Facebook's own location list. Where Facebook has no matching location the name is folded into the search text instead — you still get results near that place, but matched on words rather than geography, and a free note row says so. Paste a Facebook events URL for the city to force an exact area.
- Facebook occasionally answers a stub instead of a page. The run takes a fresh address and asks again, and only after several attempts does it write an uncharged BLOCKED row. Re-running a minute later normally clears it.
- Search results are ranked by Facebook, not by date. Use the date window if you need a specific period rather than expecting the newest events first.
- Facebook's logged-out events index does not answer every phrase. Screened over 87 ordinary event phrases, 85 returned results and a handful ("wine tasting", "pub quiz", "beer festival") returned nothing at all, from any address, with or without a city — while single words from the same phrase ("tasting") returned plenty. When a term comes back empty you get a free NO\_RESULTS row; try a shorter or more common wording.
- Recurring events are returned as the occurrence Facebook links to. The series is not expanded into one row per date.

### Questions

**Do I need a Facebook account, cookies or a token?**

No. Nothing is logged in and nothing is stored. Only public events are read, exactly as an anonymous visitor sees them.

**One of my search terms returns nothing at all. Is it broken?**

Probably not. Facebook's public events index answers most phrases but genuinely returns nothing for some of them, from every address and with or without a city. A single word from the same phrase usually works where the two-word version does not. An empty term costs you nothing — you get a free note row.

**Why do I only get 8 events for a search term?**

That is what Facebook's public events search hands an anonymous visitor for one term. Add more terms, add a city, or point the run at specific Pages — the run limit is on total events, not on sources, so going wide costs nothing extra per source.

**Can I get events near a specific city rather than everywhere?**

Yes. Put the city in `location`. It is matched against Facebook's own location list, so results are geographic rather than keyword matches. For complete control, paste a Facebook events URL for that city into `location` instead.

**What happens if an event is private or has been deleted?**

You get one uncharged row with `"_diagnostic": true` and a `NOT_FOUND` code saying so. You are never charged for it and the run still finishes successfully.

**Does a failed or empty run cost me anything?**

Only the start fee. Diagnostic rows, sample rows and events dropped by your filters are all free.

**Can I pull a Page's past events too?**

Yes — set `includePastEvents` to true and pass the Page URL in `startUrls`. A Page's public events tab mixes upcoming and past events; with the setting off, anything that has already started is dropped before it is charged.

# Actor input Schema

## `searchTerms` (type: `array`):

What to search Facebook events for - 'concert', 'startup meetup', 'food festival'. Up to 20 terms per run, each searched in turn. Facebook's public events search returns up to 8 events per term, so use several terms (and the city box below) to go wider.

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

Optional. A city name such as 'Berlin' or 'New York', or - for an exact area - a Facebook events URL for that city (https://www.facebook.com/events/explore/<city>/<id>/). A city name is looked up against Facebook's own location list; if Facebook has no matching location it is folded into the search text instead and a free note row tells you so.

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

Optional. Any mix of: a public event URL (https://www.facebook.com/events/123456789012345/), a Page URL or handle whose hosted events you want, a Group URL, a Facebook events search URL you built in the browser, or an events explore URL for a city. Up to 50 per run.

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

Total number of events to return across everything above. Keep it low while you are testing - you pay per event.

## `startingFrom` (type: `string`):

Optional and free. Drop events that start before this. Accepts 2026-09-01, a full ISO timestamp, an epoch, or a relative window such as '7 days'. Filtered events are never charged.

## `startingBefore` (type: `string`):

Optional and free. Drop events that start after this. Same formats as above.

## `category` (type: `string`):

Optional and free. Restrict the search to one of Facebook's own event categories.

## `onlineOnly` (type: `boolean`):

Optional and free. Return only events Facebook marks as online.

## `paidOnly` (type: `boolean`):

Optional and free. Ask Facebook's search for paid events only.

## `includePastEvents` (type: `boolean`):

Optional and free. Off by default, so you get upcoming events. Turn it on to also read a Page's or Group's past events.

## `proxyUrls` (type: `array`):

Leave this empty. By default the run rotates a large pool of addresses that cost you nothing per gigabyte. Fill it in only if you specifically want the traffic to leave through proxy servers you already pay for, in the form http://user:pass@host:port.

## `sessionCookies` (type: `array`):

Leave this empty unless you need it. Runs are logged out by default and that is enough for public Facebook content. Facebook shows some things only to a signed-in account, and it limits how fast any one account may read; supplying your own cookie uses your account and your own rate limit, shared with nobody. In Chrome: open facebook.com while signed in, press F12, then Application > Cookies > https://www.facebook.com, and paste the values as "c\_user=<value>; xs=<value>". One line per account. Treat these like a password: anyone with them can act as that account, and Facebook may sign the session out or restrict the account for automated use.

## Actor input object example

```json
{
  "searchTerms": [
    "startup meetup"
  ],
  "location": "Berlin",
  "maxEvents": 20
}
```

# Actor output Schema

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

Every row in the default dataset: eventId, eventUrl, name, description, startTime, startTimestamp, endTime, endTimestamp, timezone, dateText, venueName, venueAddress, venueCity, venueUrl, latitude, longitude, isOnline, onlineUrl, organizers, organizerName, organizerUrl, ticketUrl, priceRange, attendingCount, interestedCount, respondedCount, coverImageUrl, categories, isCanceled, isPast, sourceType, sourceQuery, sourceUrl. An empty, blocked or unmatched run returns a single uncharged row explaining what happened instead.

# 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 = {
    "searchTerms": [
        "startup meetup"
    ],
    "maxEvents": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("dami_studio/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 = {
    "searchTerms": ["startup meetup"],
    "maxEvents": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("dami_studio/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 '{
  "searchTerms": [
    "startup meetup"
  ],
  "maxEvents": 20
}' |
apify call dami_studio/facebook-events-scraper --silent --output-dataset

```

## MCP server setup

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