Eventbrite Scraper - Event Data: City, Date, Venue, Organizer
Pricing
from $1.90 / 1,000 event scrapes
Eventbrite Scraper - Event Data: City, Date, Venue, Organizer
Eventbrite scraper for market research, event data. Search events by city, date, category, format, online or in-person. No login, no API key, no ticket prices - the feed has none. True UTC starts from local time + IANA timezone, venue coordinates, organizer IDs, publish date, coverage row per city.
Pricing
from $1.90 / 1,000 event scrapes
Rating
0.0
(0)
Developer
Eimantas V
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Eventbrite Scraper — events by city and date
Eventbrite's own API shows you the events you own. This reads the ones you
don't. Give it country--city slugs, a search term and a date window; the
public discovery feed comes back as flat rows. No browser, no login, no API
key.
What you get per event
| Field | Notes |
|---|---|
startsAtUtc | The real instant, composed from the event's local time and its IANA zone. Not the local clock string. |
startDate / startTime / endDate / endTime / timezone | The local values exactly as Eventbrite reports them |
venue | name, city, region, country, postalCode, address, and latitude / longitude as numbers |
category, subcategory, format | Eventbrite's own taxonomy — Music / Hip Hop / Rap / Party or Social Gathering. Measured over 200 events: category and format 98%, subcategory 82.5% |
organizerTags | Free-text tags the organizer chose. Present on 90.5% |
organizerId | Stable key for grouping an organizer's whole programme |
publishedAt | When the listing went up, not when the event happens |
eventId, name, url, summary, ticketsUrl, imageUrl, isOnline, language | summary and publishedAt are 100% |
Plus one coverage summary row per location: events returned and examined, pages read against pages available, duplicates and filtered rows dropped, and whether the corpus ran out or the page budget stopped it.
Why startsAtUtc matters
Eventbrite gives you "20:00" and "America/New_York" separately. Treating
that time as UTC puts the event four or five hours out depending on the season,
and every window filter, sort and join downstream inherits the error. This
composes the instant properly, DST included:
2026-09-04 20:00 America/New_York -> 2026-09-05T00:00:00Z (EDT, UTC-4)2026-01-15 20:00 America/New_York -> 2026-01-16T01:00:00Z (EST, UTC-5)2026-09-04 20:00 Asia/Kolkata -> 2026-09-04T14:30:00Z (UTC+5:30)
If the date, the time or the zone is missing, the field is null rather than a
guessed instant.
What this does not do
There is no price data. The discovery feed carries no ticket availability at all — absent on all 200 events sampled — so ticket price, currency and sold-out status are simply not knowable from here. This Actor does not emit those fields as permanent nulls to look more complete than it is.
No organizer name, and no contact details. The row carries organizerId
and organizerTags, nothing else about the organizer. organizerId tells you
these eleven events are one operator, not who that operator is — group a city
by it and a programme falls out: cadence, categories, venues. One event is
noise; a twelve-event programme is an account. But there is no email, no phone
and no name here.
No seriesId or isCancelled either. Eventbrite defines both, and reports
both as null on all 200 events sampled, so they are not emitted. A recurring
series or a cancellation only shows on the event's own page, which this Actor
deliberately does not fetch — one request per twenty events is what makes it
cheap.
Online events have no venue. venue is null, not an object full of blank
strings. Measured over 200: absent on all 60 online events, present on all 140
in-person ones, and every one of those 140 carries real coordinates.
A location it does not recognise is reported as such. Eventbrite answers an
unrecognised discovery path with HTTP 200 and a perfectly normal-looking page
holding zero events, which is indistinguishable from a real place with nothing
scheduled. The summary row says which, in zeroEventsReason:
location-not-recognised versus none-scheduled. That is the difference
between a typo and an answer.
Everywhere else, null means Eventbrite did not report it — never zero, never
empty. A venue with a missing coordinate gets null, not latitude 0, which
is a real place in the Gulf of Guinea that a bounding-box filter would match.
Input
{"locations": ["united-states--new-york", "united-kingdom--london", "online"],"query": "tech conference","maxEventsPerLocation": 200,"startsAfter": "2026-09-01","eventType": "any"}
locations takes country--city slugs, the word online, or full
eventbrite.com/d/... URLs. A bare city name is rejected rather than guessed
at, for the reason above.
maxEventsPerLocation bounds the output; maxPagesPerLocation (default 25)
bounds the work. A narrow date filter would otherwise page to the end of a
49-page result set. Pages fetched but filtered away are never charged.
Rate limiting
Measured against the live site from one IP:
40 requests/minute 12/12 clean (also clean at 20 and 30)~60 requests in a burst 429429 lockout cleared between t+210s and t+240s
requestDelayMs defaults to 1500 — the measured-safe rate, not an optimistic
one. On a 429 the Actor waits the measured backoff once and retries; retrying
immediately only extends the lockout. Throughput scales with IPs, so use the
proxy input to run several locations quickly. Apify bills datacenter proxy per
IP per month, not per gigabyte, so it costs nothing per row.
Pricing
From $1.90 per 1,000 events — $0.0040 each on the Free plan, falling to $0.0019 on Business. Locations Eventbrite does not recognise are never charged — nor are duplicates, or rows your filters removed. A city that resolved and simply has nothing on is charged for its coverage row, because that is a real answer that cost real requests. Full workings in docs/PRICING.md.
Notes on the implementation
The events live in a window.__SERVER_DATA__ island of roughly 177 KB, and it
contains }; inside string values — so the obvious /=\s*(\{.*?\});/ match
truncates into invalid JSON. Extraction is depth-counted with string and escape
awareness, which is the only thing that terminates in the right place. There is
a test for it.
Coordinates arrive as strings ("40.7018895"). A string where the dataset
schema declares a number is rejected at push time, after the fetch has already
been paid for, so they are coerced on the way in.