An autonomous AI agent that browses the web in real-time to find you the best available tickets — live.
Ticket Hunter is a fully autonomous AI agent that takes a natural-language query like "Taylor Swift Eras Tour NYC" and — without any human intervention — searches Google, opens Ticketmaster, StubHub, SeatGeek, and other ticket platforms, navigates the pages, and returns ranked, structured ticket listings in real-time.
The agent streams its work live to the browser: you watch it browse, click, and extract data as it happens.
Built with Bright Data + Yutori N1
The agent runs as a 5-stage LangGraph pipeline, streamed live to your browser via Server-Sent Events:
User Query
│
▼
┌─────────────────────────────────────────────────────────┐
│ Stage 1 · SERP Search │
│ Bright Data SERP API searches Google for ticket sites │
│ Scores and selects the top 3 most relevant URLs │
└────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Stage 2 · Browser Pipeline │
│ Connects to Bright Data Browser API via CDP │
│ Opens each URL with a real Chromium instance │
│ Takes initial screenshot → streamed to UI live │
└────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Stage 3 · Yutori N1 Agentic Loop (up to 15 steps) │
│ N1 vision model views screenshots and decides actions │
│ Tools: navigate · click · scroll · type · screenshot │
│ Iterates until tickets are found or step limit reached │
└────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Stage 4 · Structured Extraction │
│ OpenRouter (Gemini Flash) extracts JSON from findings │
│ Fields: event, date, venue, section, row, price, url │
└────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Stage 5 · Merge & Rank │
│ Deduplicates results across platforms │
│ Sorts by price (lowest first) → returned to UI │
└─────────────────────────────────────────────────────────┘
| Layer | Technology |
|---|---|
| Framework | Next.js 16 · React 19 · TypeScript 5 |
| Styling | Tailwind CSS 4 |
| Agent Orchestration | LangGraph |
| Browser Automation | Playwright Core + Chrome DevTools Protocol (CDP) |
| Web Infrastructure | Bright Data Browser API + SERP API |
| Vision LLM | Yutori N1 (multimodal, tool-use) |
| Extraction LLM | OpenRouter → Google Gemini Flash |
| Rate Limiting | Upstash Redis (per-IP, 1 search / 24h for the demo) |
| Deployment | Vercel via GitHub Actions |
The agent autonomously detects and browses any of these platforms based on Google results:
- Ticketmaster
- StubHub
- SeatGeek
- Vivid Seats
- AXS
- TickPick
- Gametime
- Eventbrite
- Viagogo
- TicketNetwork
- Tickets.com
- Node.js 18+
- A Bright Data account with Browser API + SERP API enabled
- A Yutori N1 API key
- An OpenRouter API key
- An Upstash Redis database (for rate limiting)
git clone https://github.com/brightdata/ticket-hunter-agent.git
cd ticket-hunter-agentnpm installCreate a .env.local file in the project root:
# Yutori N1 — vision LLM for autonomous browsing
YUTORI_API_KEY=your_yutori_api_key
# Bright Data — Browser API CDP WebSocket endpoint
# Found in your Bright Data dashboard under Browser API > Access Parameters
BRD_CDP_URL=wss://brd-customer-<id>-zone-<zone>:<password>@brd.superproxy.io:9222
# Bright Data — API key for SERP and Web Unlocker
BRIGHTDATA_API_KEY=your_brightdata_api_key
BRIGHTDATA_SERP_ZONE=serp # optional, defaults to "serp"
BRIGHTDATA_WEB_UNLOCKER_ZONE=unblocker # optional, defaults to "unblocker"
# OpenRouter — structured JSON extraction via Gemini Flash
OPENROUTER_API_KEY=your_openrouter_api_key
OPENROUTER_MODEL=google/gemini-flash-1.5 # optional
# Upstash Redis — rate limiting (remove or leave blank to disable)
KV_REST_API_URL=https://your-instance.upstash.io
KV_REST_API_TOKEN=your_upstash_tokennpm run devOpen http://localhost:3000 and search for any event.
src/
├── app/
│ ├── api/search/route.ts # POST endpoint — SSE stream orchestrator
│ ├── page.tsx # Main UI page
│ └── layout.tsx # Root layout + global metadata
├── components/
│ ├── SearchForm.tsx # Query input with example prompts
│ ├── BrowserView.tsx # Live browser screenshot panels (1–3 platforms)
│ ├── StatusLog.tsx # Real-time agent activity log
│ └── ResultCard.tsx # Ticket card with price, venue, seats
├── hooks/
│ └── useTicketSearch.ts # SSE consumer + client state management
└── lib/
├── agent/
│ ├── graph.ts # LangGraph workflow definition
│ ├── state.ts # Agent state schema
│ ├── stream-events.ts # SSE event emitters
│ ├── runtime-session.ts # Browser session lifecycle
│ ├── browser-utils.ts # Playwright helpers
│ ├── tools.ts # N1 tool schemas (click, scroll, etc.)
│ └── nodes/
│ ├── serp-search.ts # Stage 1: Google SERP via Bright Data
│ ├── browser-open.ts # Stage 2: CDP browser connection
│ ├── browser-pipeline.ts # Stage 2: per-URL browsing orchestration
│ ├── n1-browse-core.ts # Stage 3: N1 agentic loop (15-step max)
│ ├── n1-browse.ts # Stage 3: N1 LangGraph node wrapper
│ ├── extract.ts # Stage 4: structured JSON extraction
│ └── merge-and-rank.ts # Stage 5: dedup + price sort
├── bright-data.ts # Bright Data SDK wrapper
├── n1-client.ts # Yutori N1 OpenAI-compatible client
├── openrouter-client.ts # OpenRouter extraction client
├── rate-limit.ts # Upstash Redis rate limiter
└── types.ts # Shared TypeScript interfaces
The repo includes a GitHub Actions workflow for automatic Vercel deployment.
Then add all environment variables in your Vercel project settings.
- Fork the repo
- Connect it to a Vercel project
- Add these secrets to your GitHub repo:
VERCEL_TOKENVERCEL_ORG_IDVERCEL_PROJECT_ID
- Add all
.env.localvariables to Vercel's environment settings - Push to
main— the workflow deploys automatically
npm run build
npx vercel deploy --prodEach result returned by the agent follows this structure:
interface TicketResult {
eventName: string; // "Taylor Swift | The Eras Tour"
eventDate: string; // "Friday, June 7, 2025"
venue: string; // "MetLife Stadium"
city: string; // "East Rutherford, NJ"
ticketType: string; // "Floor A · General Admission"
section: string; // "GA Floor"
row: string; // "N/A"
seats: string; // "2 available"
quantity: number; // 2
price: string; // "$380"
currency: string; // "USD"
platform: string; // "StubHub"
url: string; // Deep link to the listing
notes: string; // Any additional context
}The agent communicates with the frontend via Server-Sent Events (SSE). Events emitted during a search:
| Event | Payload | Description |
|---|---|---|
status |
{ message, level } |
Agent log entry (INFO, ACTION, WARN, DONE, etc.) |
screenshot |
{ data, source } |
Base64 browser screenshot streamed live |
inspect_url |
{ url, source } |
Current URL the browser has navigated to |
result |
{ tickets, finalAnswer } |
Final structured ticket results |
error |
{ message } |
Agent error |
done |
— | Stream complete |
The live demo enforces 1 search per IP per 24 hours via Upstash Redis.
When running locally with your own keys, this limit is not enforced unless you configure Upstash in your .env.local.
|
Bright Data provides the web infrastructure that makes the agent possible:
|
Yutori N1 is the multimodal vision LLM at the core of the agent loop:
|
MIT © Bright Data & Yutori