     [Blog](https://scrapfly.io/blog)   /  [beautifulsoup](https://scrapfly.io/blog/tag/beautifulsoup)   /  [How to Scrape Ticketmaster in 2026](https://scrapfly.io/blog/posts/how-to-scrape-ticketmaster)   # How to Scrape Ticketmaster in 2026

 by [Hisham Medhat](https://scrapfly.io/blog/author/hisham) Jun 01, 2026 13 min read [\#beautifulsoup](https://scrapfly.io/blog/tag/beautifulsoup) [\#python](https://scrapfly.io/blog/tag/python) [\#requests](https://scrapfly.io/blog/tag/requests) [\#scrapeguide](https://scrapfly.io/blog/tag/scrapeguide) 

 [  ](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-ticketmaster "Share on LinkedIn")    

 

 

         

   **Web Scraping API — Anti-Bot Bypass**Bypass any anti-scraper system and automatically resolve JavaScript and fingerprint challenges.

 

 [ Learn More  ](https://scrapfly.io/products/web-scraping-api#features) [  Docs ](https://scrapfly.io/docs/scrape-api/getting-started#features) 

 

 

Ticketmaster lists events across most major venues and promoters, so it's where most live-event datasets start. Tour routing, secondary-market pricing signals, and venue tracking all begin with this catalog. The catch is that the site is a hashed-class React app sitting behind enterprise bot detection. Any scraper built on visible CSS selectors breaks within a release cycle. The page itself returns 403s to plain HTTP requests well before you reach a parser.

This guide takes the structured-data route instead. Every Ticketmaster artist and discovery page ships its event catalog as JSON-LD inside `<script type="application/ld+json">` blocks, and that schema stays stable across redeploys. We'll use [Scrapfly's Web Scraping API](https://scrapfly.io/web-scraping-api) to clear the bot layer. Then we'll parse `MusicGroup`, `MusicEvent`, and `TheaterEvent` blocks directly from the rendered HTML.

[**Latest Ticketmaster Scraper Code**github.com/scrapfly/scrapfly-scrapers/ticketmaster-scraper](https://github.com/scrapfly/scrapfly-scrapers/tree/main/ticketmaster-scraper)



## Key Takeaways

- Parse JSON-LD on Ticketmaster pages, not CSS selectors. `MusicGroup` blocks carry artist name and aggregate rating, while `MusicEvent` and `TheaterEvent` blocks carry event name, `startDate`, `location.name`, `location.address`, and `offers.url`. Selectors like `sc-a4c9d98c-1` change between deploys and silently break scrapers.
- Genre and discovery metadata live in a separate `window.digitalData` JavaScript object. Extract it with a balanced-brace JSON walker rather than a regex, since the payload contains nested strings and braces that fool naive matching.
- Ticketmaster blocks plain HTTP requests fast. User-Agent rotation and session reuse help against soft checks, but neither defeats the production bot layer on its own.
- The discovery feed is filter-driven: compose `classificationId`, `startDate`, and `endDate` into the query string, and the same JSON-LD parser runs across any slice of the catalog with a concurrent fetch loop.
- For production Ticketmaster scraping, [Scrapfly's Web Scraping API](https://scrapfly.io/web-scraping-api) with `asp=True` and `render_js=True` returns clean HTML with the JSON-LD blocks already populated.

**Get web scraping tips in your inbox**Trusted by 100K+ developers and 30K+ enterprises. Unsubscribe anytime.







## Why Scrape Ticketmaster?

Ticketmaster lists shows from almost every major artist and venue, so the catalog is a single source for live-event data at scale. Each event page carries the venue name, address, date, lineup, and a ticket URL.

There are three common use cases:

- Promoters and analysts track tour routing, ticket prices, and venue availability across regions.
- Secondary-market tools watch new on-sale dates and pull pricing signals as inventory shifts.
- Fan-facing apps surface upcoming dates for specific artists, genres, or cities without paying for the Discovery API quota.

The data you need is already on the public pages. The hard part is getting clean HTML back from a request.

## Understanding Ticketmaster's Page Structure

Ticketmaster builds two page types worth scraping. Artist pages like `/imagine-dragons-tickets/artist/1435919` list every upcoming show for one artist. Discovery pages like `/discover/concerts` list events across the whole catalog with pagination.

Both page types ship the same structured data. Inside the HTML you'll find one or more `<script type="application/ld+json">` blocks containing:

- `MusicGroup` (or `TheaterGroup`) with the artist name, aggregate rating, and review count.
- `MusicEvent` (or `TheaterEvent`) with event name, `startDate`, `location.name`, `location.address`, and `offers.url`.

Genre and category metadata live in a separate JavaScript object, `window.digitalData`, attached to a `<script id="digitalData">` tag. That object carries the discovery classifications Ticketmaster uses internally for filters and recommendations.

The visible HTML uses styled-components, which generates rotating class names like `sc-a4c9d98c-1` and `VisuallyHidden-sc-8buqks-0`. These hashes change on every deploy, so any selector chain built on them rots fast. JSON-LD is the stable contract.

## How Does Ticketmaster Block Scrapers?

Ticketmaster runs an enterprise bot stack that catches plain Python requests on the first hit. A bare `requests.get()` against an artist URL returns 403 before the HTML ever renders.

There are three layers in play:

- TLS and HTTP/2 fingerprinting. The server compares your TLS handshake and HTTP/2 SETTINGS frame against real browser profiles. A `requests` or `httpx` client looks nothing like Chrome.
- Behavior and header checks. Ticketmaster scores risk on missing `Sec-CH-UA` hints, mismatched `Accept-Language`, and the lack of a referer chain before it serves the page.
- Client-side challenges. JavaScript probes the browser environment for canvas, WebGL, and timing signals, then writes a clearance cookie on success.

Rotating User-Agents and adding delays cuts down on soft blocks, but doesn't clear the JS challenge or fingerprint checks. For that, you need a real browser stack or a bypass service.

[How to Bypass Anti-Bot Protection When Web ScrapingLearn how anti-bot systems detect scrapers and 5 universal bypass techniques including proxy rotation, fingerprinting, and fortified headless browsers.](https://scrapfly.io/blog/posts/how-to-bypass-anti-bot-protection-when-web-scraping)



## How to Set Up Scrapfly for Ticketmaster

The whole scraper runs through the Scrapfly Python SDK. Install it first, then configure a base request profile that handles the bot layer and JavaScript rendering in one place.

bash```bash
pip install scrapfly-sdk
```



Get an API key from the [Scrapfly dashboard](https://scrapfly.io/dashboard) and export it as `SCRAPFLY_KEY`. The SDK wraps the Web Scraping API and exposes `ScrapflyClient` and `ScrapeConfig`.

python```python
import os
import json
import re
import urllib.parse
from scrapfly import ScrapeConfig, ScrapflyClient

SCRAPFLY = ScrapflyClient(key=os.environ["SCRAPFLY_KEY"])

BASE_CONFIG = {
    "asp": True,        # bypass Ticketmaster's bot detection
    "render_js": True,  # render the React app so JSON-LD is populated
}
```



`asp=True` turns on Anti-Scraping Protection, which solves the TLS, behavior, and JavaScript challenges automatically. `render_js=True` waits for the React app to hydrate before Scrapfly returns the HTML, so the parser sees fully populated JSON-LD `<script>` tags. Every snippet below reuses this `BASE_CONFIG`.

## How Do You Scrape Ticketmaster Artist Pages?

Artist pages are the densest data target on Ticketmaster. A single URL like `https://www.ticketmaster.com/imagine-dragons-tickets/artist/1435919` carries the artist name, aggregate rating, review count, genre, and every upcoming show with venue and ticket link.

The parser walks every `<script type="application/ld+json">` block on the page. It collects `MusicGroup` or `TheaterGroup` entries as the artist record, and appends `MusicEvent` or `TheaterEvent` entries to the events list.

python```python
def parse_artist_page(result):
    """Extract artist info and events from JSON-LD blocks on a Ticketmaster artist page."""
    sel = result.selector
    artist = None
    events = []

    for script in sel.xpath('//script[@type="application/ld+json"]/text()').getall():
        try:
            data = json.loads(script)
        except json.JSONDecodeError:
            continue
        items = data if isinstance(data, list) else [data]
        for item in items:
            kind = item.get("@type")
            if kind in ("MusicGroup", "TheaterGroup"):
                artist = item
            elif kind in ("MusicEvent", "TheaterEvent"):
                events.append(item)

    rating = (artist or {}).get("aggregateRating") or {}

    # genre lives in window.digitalData, not the JSON-LD blocks
    genre = None
    digital_data_script = sel.xpath('//script[@id="digitalData"]/text()').get()
    if digital_data_script:
        digital_data = extract_balanced_dict(digital_data_script, "window.digitalData=")
        if digital_data:
            attraction = (
                digital_data.get("page", {}).get("attributes", {})
                .get("discovery", {}).get("attraction", [])
            )
            if attraction:
                classifications = attraction[0].get("classifications", {})
                genre = (classifications.get("genre") or {}).get("name")

    return {
        "artist_name": (artist or {}).get("name", ""),
        "ratingValue": rating.get("ratingValue"),
        "bestRating": rating.get("bestRating"),
        "ratingCount": rating.get("ratingCount"),
        "genre": genre,
        "events_count": len(events),
        "events": events,
        "reviews": (artist or {}).get("reviews", []),
    }
```



Each `MusicEvent` already exposes `name`, `startDate`, `location.name`, `location.address`, and `offers.url`, so you get clean event data without touching the visible list markup. The function returns a flat dict with the artist record and the full event array.

Genre lives outside the JSON-LD blocks. Ticketmaster writes it into a `window.digitalData=...` assignment inside a `<script id="digitalData">` tag, alongside other discovery metadata. A regex won't work here because the payload contains nested strings and braces, so we count braces instead.

python```python
def extract_balanced_dict(text, start_pattern):
    """Extract a balanced JSON object from a JS variable assignment."""
    start_idx = text.find(start_pattern)
    if start_idx == -1:
        return None
    brace_start = text.find("{", start_idx)
    if brace_start == -1:
        return None
    brace_count = 0
    for i in range(brace_start, len(text)):
        if text[i] == "{":
            brace_count += 1
        elif text[i] == "}":
            brace_count -= 1
            if brace_count == 0:
                try:
                    return json.loads(text[brace_start:i + 1])
                except json.JSONDecodeError:
                    return None
    return None
```



This helper is a general technique for any site that embeds JSON inside a JavaScript object assignment. Pass it the full script text and the prefix (here, `window.digitalData=`) and it returns a Python dict ready to traverse.

To run the parser, send the URL through Scrapfly and feed the result in. The `concurrent_scrape` helper handles multiple artists in parallel.

python```python
async def scrape_artist(urls):
    """Scrape multiple Ticketmaster artist pages concurrently."""
    configs = [ScrapeConfig(url, **BASE_CONFIG) for url in urls]
    data = []
    async for response in SCRAPFLY.concurrent_scrape(configs):
        data.append(parse_artist_page(response))
    return data
```



 Example Outputjson```json

{
  "artist_name": "Imagine Dragons",
  "ratingValue": 4.7,
  "bestRating": 5,
  "ratingCount": 8852,
  "genre": "Rock",
  "events_count": 7,
  "events": [
    {
      "@type": "MusicEvent",
      "name": "Imagine Dragons (21 and Over)",
      "startDate": "2026-07-23T20:00:00",
      "url": "https://www.ticketmaster.com/event/Z7r9jZ1A7xZ4k",
      "location": {
        "name": "Yaamava Theater",
        "address": {"addressLocality": "Highland", "addressRegion": "CA"}
      },
      "offers": {"url": "https://www.ticketmaster.com/event/Z7r9jZ1A7xZ4k", "availability": "http://schema.org/InStock"}
    }
  ],
  "reviews": ["... 10 review objects ..."]
}
  
```



The output gives you a flat artist record plus the full events array. Each event keeps the same `MusicEvent` shape Ticketmaster ships in JSON-LD. Pass it straight to downstream code without renaming fields.

## How Do You Scrape the Ticketmaster Discovery Feed?

The discovery feed at `https://www.ticketmaster.com/discover/concerts` lists upcoming concerts across the entire catalog. Use it as the entry point when you don't know which artists to track, or when you want to sweep a city or genre.

Discovery pages embed the same `MusicEvent` JSON-LD blocks as artist pages, so the parser logic is similar. The difference is that you also want the global event count for planning, which Ticketmaster renders into a visible span on the page.

python```python
def parse_discovery_response(result):
    """Parse Ticketmaster discovery page event listings from JSON-LD."""
    sel = result.selector
    events = []

    for script in sel.xpath('//script[@type="application/ld+json"]/text()').getall():
        try:
            data = json.loads(script)
        except json.JSONDecodeError:
            continue
        event_list = data if isinstance(data, list) else [data]
        for event_data in event_list:
            if event_data.get("@type") != "MusicEvent":
                continue
            start_date = event_data.get("startDate", "")
            date = start_date.split("T")[0] if start_date else ""
            time = start_date.split("T")[1] if "T" in start_date else None
            location = event_data.get("location", {}) or {}
            address = location.get("address", {}) or {}
            city = address.get("addressLocality", "")
            state = address.get("addressRegion", "")
            venue_location = f"{city}, {state}".strip(", ")
            offers = event_data.get("offers", {}) or {}
            ticket_url = offers.get("url") or event_data.get("url", "")
            events.append({
                "event_name": event_data.get("name", ""),
                "event_url": event_data.get("url", ""),
                "date": date,
                "time": time,
                "venue_name": location.get("name", ""),
                "venue_location": venue_location,
                "ticket_url": ticket_url,
            })

    total_text = sel.xpath(
        "//span[@aria-live='polite' and contains(@class, 'gOraUu')]/text()"
    ).get()
    total_count = len(events)
    if total_text:
        match = re.search(r"(\d+)", total_text)
        if match:
            total_count = int(match.group(1))

    return {
        "events": events,
        "events_count": len(events),
        "total_count": total_count,
    }
```



`parse_discovery_response` returns a dict with three fields. `events_count` is the number of events on the current page, `total_count` is the global event total parsed from the visible header span, and `events` is the parsed list. Each event carries `event_name`, `event_url`, `date`, `time`, `venue_name`, `venue_location`, and `ticket_url`.

The wrapper below merges any extra query parameters (classification ID, start and end dates) into the base URL before sending it to Scrapfly. Classification IDs come from the Discovery API's classifications endpoint.

python```python
async def scrape_discovery(base_url, **kwargs):
    """Scrape a Ticketmaster discovery URL with optional query params."""
    parts = list(urllib.parse.urlparse(base_url))
    query = dict(urllib.parse.parse_qsl(parts[4]))
    query.update(kwargs)
    parts[4] = urllib.parse.urlencode(query)
    url = urllib.parse.urlunparse(parts)

    result = await SCRAPFLY.async_scrape(ScrapeConfig(url, **BASE_CONFIG))
    return parse_discovery_response(result)
```



Pass `classificationId`, `startDate`, and `endDate` as keyword arguments to scope the sweep, or build a list of `ScrapeConfig` objects for `concurrent_scrape` to fetch several filtered slices in parallel.



Scrapfly

#### Extract structured data automatically?

Scrapfly's Extraction API uses AI to turn any webpage into structured data — no selectors needed.

[Try Free →](https://scrapfly.io/register)## Powering Ticketmaster Scraping with Scrapfly



Scrapfly provides web scraping, screenshot, and extraction APIs for data collection at scale. For Ticketmaster, the [Web Scraping API](https://scrapfly.io/web-scraping-api) handles the bot detection, TLS fingerprinting, and JavaScript rendering. The JSON-LD parsers above keep working as the site evolves.

- [Anti-Scraping Protection bypass](https://scrapfly.io/docs/scrape-api/anti-scraping-protection) clears Ticketmaster's bot checks automatically with `asp=True`.
- [JavaScript rendering](https://scrapfly.io/docs/scrape-api/javascript-rendering) runs the React app in a real cloud browser so the parser sees populated JSON-LD `<script>` blocks.
- [Smart proxy rotation](https://scrapfly.io/docs/scrape-api/proxy) across 130M+ residential IPs in 120+ countries for regional discovery sweeps.
- [Smart caching](https://scrapfly.io/docs/scrape-api/getting-started#api_param_cache) keeps repeat scrapes cheap during parser development.
- [Python SDK](https://scrapfly.io/docs/sdk/python) with `concurrent_scrape` for parallel artist crawls and discovery sweeps.

With `asp=True` and `render_js=True`, the `parse_artist_page` and `parse_discovery_response` functions drop into a concurrent crawl loop with no proxy pools to maintain.

### Web Scraping API

Scrape any website with our powerful API. Anti-bot bypass, JavaScript rendering, and rotating proxies built-in.



[Try Web Scraping API](https://scrapfly.io/docs/scrape-api/getting-started)





## FAQ

Does the BOTS Act make Ticketmaster scraping illegal?The BOTS Act targets software that defeats ticketing access controls to bulk-buy or resell tickets, not read-only collection of public listings. Scraping event names, dates, and venues for analysis stays clear of it, but automating checkout or circumventing purchase limits does not.







Is it legal to scrape public Ticketmaster data?In *hiQ Labs v. LinkedIn*, US courts held that scraping publicly accessible data does not violate the Computer Fraud and Abuse Act. That covers public event listings, though it does not override Ticketmaster's terms of service, so review your jurisdiction and use case before running production crawls.







Why not use the Ticketmaster Discovery API?The official Discovery API is the cleaner path when your use case fits its limits (free with a key, 5,000 calls/day, 5 RPS). Scraping public pages is the answer when you need volume beyond those limits, fields the API doesn't expose, or a fallback when terms change.







How do I widen a discovery sweep?Scope the query with `classificationId`, `startDate`, and `endDate` rather than crawling page by page. The `total_count` field reports how many events match the current filter, so you can split a broad date range into narrower filtered requests and fetch them concurrently.







What breaks first when Ticketmaster updates the site?The styled-components class names rotate on every deploy, so any CSS-selector scraper breaks fast. The JSON-LD blocks and `window.digitalData` object have been stable for years.









## Summary

Scraping Ticketmaster comes down to two things. First, getting past the bot layer to receive clean HTML. Second, parsing the JSON-LD blocks the site already ships inside its own script tags.

Artist pages carry `MusicGroup` and `MusicEvent` entries. Discovery pages carry `MusicEvent` arrays plus a visible total-count span. Genre lives in `window.digitalData`, which a balanced-brace extractor pulls cleanly from the JS payload.

[Scrapfly's Web Scraping API](https://scrapfly.io/web-scraping-api) handles the bot detection and JavaScript rendering. The `parse_artist_page` and `parse_discovery_response` functions in this guide drop into a concurrent crawl loop. No proxy pools, no TLS tuning, and no CSS selectors to repair after every Ticketmaster deploy.



Legal Disclaimer and PrecautionsThis tutorial covers popular web scraping techniques for education. Interacting with public servers requires diligence and respect:

- Do not scrape at rates that could damage the website.
- Do not scrape data that's not available publicly.
- Do not store PII of EU citizens protected by GDPR.
- Do not repurpose *entire* public datasets which can be illegal in some countries.

Scrapfly does not offer legal advice but these are good general rules to follow. For more you should consult a lawyer.

 

   Table of Contents















 

  Table of Contents- [Key Takeaways](#key-takeaways)
- [Why Scrape Ticketmaster?](#why-scrape-ticketmaster)
- [Understanding Ticketmaster's Page Structure](#understanding-ticketmaster-s-page-structure)
- [How Does Ticketmaster Block Scrapers?](#how-does-ticketmaster-block-scrapers)
- [How to Set Up Scrapfly for Ticketmaster](#how-to-set-up-scrapfly-for-ticketmaster)
- [How Do You Scrape Ticketmaster Artist Pages?](#how-do-you-scrape-ticketmaster-artist-pages)
- [How Do You Scrape the Ticketmaster Discovery Feed?](#how-do-you-scrape-the-ticketmaster-discovery-feed)
- [Powering Ticketmaster Scraping with Scrapfly](#powering-ticketmaster-scraping-with-scrapfly)
- [Web Scraping API](#web-scraping-api)
- [FAQ](#faq)
- [Summary](#summary)
 
    Join the Newsletter  Get monthly web scraping insights 

 

  



Scale Your Web Scraping

Anti-bot bypass, browser rendering, and rotating proxies, all in one API. Start with 1,000 free credits.

  No credit card required  1,000 free API credits  Anti-bot bypass included 

 [Start Free](https://scrapfly.io/register) [View Docs](https://scrapfly.io/docs/onboarding) 

 Not ready? Get our newsletter instead. 

 

## Explore this Article with AI

 [ ChatGPT ](https://chat.openai.com/?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-ticketmaster) [ Gemini ](https://www.google.com/search?udm=50&aep=11&q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-ticketmaster) [ Grok ](https://x.com/i/grok?text=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-ticketmaster) [ Perplexity ](https://www.perplexity.ai/search/new?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-ticketmaster) [ Claude ](https://claude.ai/new?q=Summarize%20this%20page%3A%20https%3A%2F%2Fscrapfly.io%2Fblog%2Fposts%2Fhow-to-scrape-ticketmaster) 



 ## Related Articles

 [  

 python data-parsing 

### How to Parse Web Data with Python and Beautifulsoup

Beautifulsoup is one the most popular libraries in web scraping. In this tutorial, we'll take a hand-on overview of how ...

 

 ](https://scrapfly.io/blog/posts/web-scraping-with-python-beautifulsoup) [  

 http python 

### Guide to Python requests POST method

Discover how to use Python's requests library for POST requests, including JSON, form data, and file uploads, along with...

 

 ](https://scrapfly.io/blog/posts/how-to-python-requests-post) [     

 python beautifulsoup 

### How to Scrape Zoro.com Without Getting Blocked in 2026

Scrape Zoro.com product titles, prices, SKUs, and attributes with Python. Bypass DataDome anti-bot protection using stab...

 

 ](https://scrapfly.io/blog/posts/how-to-scrape-zoro-dot-com) 

  ## Related Questions

- [ Q How to save and load cookies in Python requests? ](https://scrapfly.io/blog/answers/save-and-load-cookies-in-requests-python)
- [ Q What are some BeautifulSoup alternatives in Python? ](https://scrapfly.io/blog/answers/what-are-some-beautifulsoup-alternatives)
- [ Q How to handle popup dialogs in Playwright? ](https://scrapfly.io/blog/answers/how-to-click-on-alert-dialog-in-playwright)
- [ Q Scrapy vs Beautifulsoup - what's the difference? ](https://scrapfly.io/blog/answers/scrapy-vs-beautifulsoup)
 
  



   



 Extract structured data with AI, **1,000 free credits** [Start Free](https://scrapfly.io/register)