Design, methodology, analysis, and revenue recommendations
Each scrape captures every general-admission tour-time price across all four attraction booking pages.
| Attraction | Rows | Dates | Data window |
|---|---|---|---|
| Empire State Building | 9,568 | 172 | Apr 12 – Oct 1, 2026 |
| Edge Hudson Yards | 20,868 | 267 | Apr 12, 2026 – Jan 4, 2027 |
| Summit One Vanderbilt | 5,371 | 199 | Apr 12 – Oct 28, 2026 |
| Top of the Rock | 22,929 | 264 | Apr 12, 2026 – Jan 1, 2027 |
ESB's booking window extends approximately six months forward; Edge and TOR extend roughly nine months. All analysis is bounded by ESB's window, since that is the shared date range across all four attractions. → Browse in Price Tracker
For this 48-hour prototype, prices are stored in a local SQLite database, with static JSON files published to GitHub and the dashboard served as a fully static site with no server required.
The recommended production path is Azure PostgreSQL for the data layer, Blob Storage for the JSON payload, and Entra ID SSO for access control. The full architecture and cost estimate ($58–99/month) are covered in Section 6.
Prices are collected once per day. Competitor prices move by date and tour time rather than by the hour, a daily cadence captures all meaningful changes. ESB and Edge both reprice dynamically. Between two consecutive daily scrapes, Edge repriced five tour times upward.
The scraper is written in Python (a widely-used programming language) using Playwright (a browser automation library) and headless Chromium (a browser engine that runs without a visible window). For each attraction, it opens the public booking widget, steps through the forward calendar date by date, and reads every available tour time and its listed price. This is the same interaction any guest would perform manually. All data collected is publicly visible.
Each daily run scrapes all four attractions, validates that row counts are within expected ranges, rebuilds the static JSON payload, and publishes. If any attraction returns zero rows, the run is blocked and the prior day's data remains live.
During development, AI-assisted testing revealed that several competitor booking systems expose API endpoints capable of returning real-time pricing and availability data without browser interaction. This approach was not used; querying proprietary booking infrastructure without authorization would likely violate each platform's terms of service.
This analysis covers general-admission pricing only: one adult, one ticket, the lowest-priced deck entry for each attraction. Premium and upsell tier comparisons are addressed in Section 6.
The database stores one row per attraction, per tour time, per travel date, per scrape run. Key fields are attraction, scrape_date, travel_date, tour_time, price_cents (null where sold out), and tour_group (ESB only).
Attractions sell at different intervals: ESB every 15 minutes, Summit every 30 minutes, Edge and TOR every 10 minutes. Cross-attraction comparisons match to nearest available tour time within ±30 minutes. → See tour times in Tracker
| Attraction | Fee | GA base | 1-ticket all-in | 4-ticket all-in |
|---|---|---|---|---|
| ESB | $5/order | $44 | $49 | $181 |
| Edge | $2/ticket | $40 | $42 | $168 |
| Summit | $3/order | $44 | $47 | $179 |
| TOR | Embedded | $42 | $42 | $168 |
ESB carries the highest all-in price for a solo buyer ($49 vs. Edge $42). The fee structure alone drives this gap. Base prices across all four attractions are within $2–4 of each other. → See price matrix
All dashboard analyses currently compare base fares before booking fees. Because fee structures differ across attractions (per-order, per-ticket, embedded), a true apples-to-apples comparison requires an all-in view that layers fees on top of every price point. The ideal implementation is a toggle on each analysis page that switches between base-fare and all-in pricing, adjustable by party size. This was scoped but not built within the 48-hour window. It is the highest-priority enhancement for the next iteration.
Sunset premium = peak evening price minus same-date noon price. Noon is the baseline because every attraction sells it and no attraction prices noon as a sunset-window hour. The result is a consistent, apples-to-apples comparison across all four.
Sold-out tour times: stored as null, not zero. Last known price carries forward. Zero-row scrapes block publish; prior day's data remains live. Anomalies are flagged in the log, not deleted. → Full methodology
All AI-assisted work in this project used Claude Code, Anthropic's command-line coding agent powered by Claude Opus 4.6.
Claude Code was used to design and implement the four attraction scrapers, the SQLite database schema, the validation pipeline, all five dashboard pages, the sunset premium detection algorithm, and an embedded chatbot for plain-English data queries. → See the dashboard
The full system (scrapers, database, pipeline, and dashboard) was built in 48 hours. A comparable build without AI assistance would conservatively require five to six weeks with a two-person development team.
No engineering background. One revenue analyst directing Claude Code as a technical co-builder.
Claude Code produced the code. The analyst specified what to build and made every pricing call: which fee structure to use as the comparison basis, which baseline to anchor the sunset upsell calculation, how to distinguish a scraper failure from a low-demand day. The technical scope: four scrapers, SQLite database, validation pipeline, five dashboard pages, embedded chatbot. Built in 48 hours. Claude Code launched in February 2025 and has released major capability updates every few weeks since.
Competitor APIs found during testing were not used; querying proprietary booking infrastructure would likely violate terms of service. Claude Code cannot access login-required rates or draw on real-time web data. The project required modular documentation to manage the model's context window. Each scraper was manually verified against a live browser session before production use.
ESB and Edge reprice dynamically, with prices that change by date, tour time, and demand signals. Summit and TOR use variable fixed tiers set in advance, with no intraday repricing observed. → Explore in Trends
| Attraction | Range | Distinct | How it moves |
|---|---|---|---|
| ESB | $44–$62 | 7 | Dynamic. Capacity driven. |
| Edge | $42–$69 | 26 | Dynamic. Live repricing observed. |
| Summit | $44–$68 | 6 | Variable. Base + $13 sunset step. |
| TOR | $42–$71 | 9 | Variable. $3 intervals, fixed once set. |
Live repricing (Apr 11 → Apr 12): Edge repriced 5 tour times upward ($50→$51, $65→$67, etc.). No other attraction changed.
ESB has the lowest price on 1,022 of 1,289 sunset tour times (79%). These are tour times where all four attractions were at sunset pricing, an apples-to-apples comparison. Each ESB Sunset/Twilight tour time matched to nearest competitor sunset-priced time within ±30 min. → Explore in Sunset Analysis
| Comparison | ESB lowest |
|---|---|
| vs. Edge | 93% |
| vs. Summit | 84% |
| vs. TOR | 94% |
ESB's $62 ceiling is the lowest in the comp set. Edge peaks at $69, Summit at $68, TOR at $71. The average gap to TOR across matched sunset tour times is $5.67, with a maximum of $13. ESB is systematically underpriced during the window where competitor prices are highest.
On a solo all-in basis, ESB is the most expensive at $49 (see fee structure in Section 2). This is a fixable structural issue, not a base-price problem.
All four attractions price by time of day. ESB is the only one that does not vary price by day of week. → Explore in Trends
Weekend uplift: ESB +0.5% vs. Edge +5.8%, Summit +5.3%, TOR +2.3%. Calculation: (avg weekend price - avg weekday price) / avg weekday price, across all tour times in the forward calendar.
The forward calendar covers peak summer and major holiday windows. On a July 5th Sunday, ESB's average available price ($50.16) is within $0.50 of a quiet April weekday. There is limited holiday or seasonal premium in the pricing model. Every competitor charges more on high-traffic days.
Five directional recommendations based on public competitor pricing data.
These recommendations are preliminary and directional. Public pricing data shows where opportunities may exist, but finalizing any recommendation requires internal data: conversion rates, capacity utilization, channel mix, and price elasticity. The validation inputs in Section 6 list exactly what is needed to size each opportunity and set implementation thresholds.
ESB's current sunset pricing tops out at $62 across three tiers ($56 / $58 / $62), the lowest ceiling in the comp set.
Action: Add $64 for high-demand sunset dates and raise the floor from $56 to $58. New structure: $58 / $62 / $64. Capacity trigger: sell-through ≥ X% and ≥1 competitor at $64+.
ESB has the lowest price on 1,022 of 1,289 matched sunset tour times (79%), at tour times where all four attractions were at sunset pricing. By tier: $56 is lowest 96% of the time, $58 is lowest 81%, and $62 is lowest only 63%, indicating meaningful headroom at the top tier. → See full sunset comparison
ESB's sunset pricing currently ends at astronomical sunset, after which tickets revert to the base rate. The sky retains visible color for roughly 30 minutes after sunset, a window that TOR monetizes by holding elevated pricing more than two hours past astronomical sunset.
Action: A 30-minute extension to sunset pricing adds one additional tour time per date to the premium tier.
Capacity dimension: Sunset visitors tend to stay longer as the light fades, which creates throughput pressure. The extended window would require a reduction in per-tour-time capacity to prevent overcrowding: higher price per ticket, fewer tickets per tour time.
Market evidence: Twilight lasts approximately 30 minutes after sunset. TOR holds elevated pricing well past that window. ESB's current structure leaves that 30-minute twilight period priced at the base rate. → See sunset timing data
Edge offers an Advance Saver discount of up to 35% off for bookings made 14 or more days in advance. ESB, Summit, and TOR have no equivalent.
Action: Offer 10–15% off GA for bookings made 21 or more days in advance, through the direct channel only, excluding sunset-window tour times to protect premium tier integrity.
Math: At 15% off a $44 base, the discounted price would be $37.40, or $42.40 all-in with the booking fee. That floor needs to be validated against OTA net rates before launch to confirm the direct-channel discount doesn't undercut existing reseller rates.
Competitive gap: Edge is the only attraction using time-of-purchase as a demand lever. A 21-day window sits comfortably outside the core booking curve for most leisure guests.
Edge launched a $99 annual pass in March 2026. It is the only attraction in the comp set with a paid membership. ESB has no equivalent.
Action: A premium ESB membership at $400–$500 per year, including priority access for the member plus one guest, a 24-visit annual cap, and benefits from building tenants, would occupy a distinct tier above Edge's volume-oriented pass and leverage ESB's unique tenanted-tower footprint, which no competitor can replicate.
Gate and verification: Any membership requires access control at entry: digital verification plus photo-ID check against the membership account. This prevents pass-sharing. If tenant benefits are included, a membership card or app-based credential linked to the same account would cover both observatory entry and tenant access.
Differentiation: Edge's $99 pass demonstrates willingness-to-pay for recurring access. ESB is the only attraction with a tenanted tower - tenant partnerships are a structural advantage Summit, TOR, and Edge cannot replicate.
Why this matters: Per Section 2, ESB's $5 flat fee makes solo tickets $49 vs. Edge's $42. OTAs charge no consumer-facing fee, so direct can appear more expensive than resellers for the same product.
Action: A $2-per-ticket fee reduces the solo all-in price from $49 to $46. ESB clears Summit ($47) and closes to within $4 of Edge ($42).
All-in prices (base + fees)
| Tickets | ESB now | ESB proposed | Edge | Summit | TOR |
|---|---|---|---|---|---|
| 1 | $49 | $46 | $42 | $47 | $42 |
| 4 | $181 | $184 | $168 | $179 | $168 |
The case: The fee structure (not the base price) is what makes ESB the highest-priced solo option. OTA-listed prices carry no consumer-facing fee, so the direct channel can display a higher price than resellers. A per-ticket fee closes the gap without touching the $44 base. This is the lowest-risk recommendation: a backend configuration change, testable via 30-day A/B. → See fee comparison in Overview
Internal data needed to size and finalize the Section 5 recommendations. Click any row for details.
Ticketing / Sales (Accounting)
Operations
Partners / External
Legal
Yield trigger rule: When ESB utilization exceeds 80% on a tour time AND ESB price is below the lowest competitor, raise price. The Price Shop provides the demand signal (competitor rates). The ticketing system provides the supply signal (remaining capacity). → See live competitor rates
| Component | Cost/mo |
|---|---|
Container Apps Jobs (4 scrapers)$5–$15What: Serverless containers that run on a schedule (daily at 6 AM ET). Does: Each scraper (ESB, Edge, Summit, TOR) runs as its own container job. Playwright + Chromium bundled in Docker image. Scale-to-zero when idle. Why: No VM to manage. Adding a new competitor = add a container, not a person. Horizontally scalable and cost-efficient. |
|
PostgreSQL Flexible$35–$55What: Azure Database for PostgreSQL - a fully managed relational database. Does: Replaces SQLite. Full ACID compliance, row-level locking, connection pooling via PgBouncer. Append-only price history for unlimited lookback. Why: No file-lock contention. Automated backups, point-in-time restore, geo-redundancy option. Connection string in Key Vault, not code. |
|
Blob + CDN$4–$10What: Azure Blob Storage (hot tier) with Azure CDN for global delivery. Does: Stores the static JSON payload. Each daily build is a dated snapshot. CDN caches at edge locations for fast page loads worldwide. Why: Versioned blobs enable instant rollback. Lifecycle policy moves old data to cool/archive after 90 days. Sub-100ms delivery globally. |
|
Static Web Apps + SSO$9What: Azure Static Web Apps with built-in Entra ID (Azure AD) authentication. Does: Hosts the dashboard HTML/JS. Auto-deploys on GitHub push. SSO via existing corporate identity - no shared passwords. Why: IT provisions access via existing Entra ID tenant. Role-based access control. Audit log of who accessed what, when. Managed TLS certs. |
|
Key Vault + Monitor$5–$10What: Azure Key Vault for secrets management + Azure Monitor for observability. Does: Key Vault stores DB credentials, API tokens. Monitor tracks scraper health, row counts, errors. Alert rules fire to Teams/email on failure. Why: No secrets in environment variables or code. Managed Identity auth - containers authenticate to Key Vault without stored credentials. Full audit trail. |
|
| Total | $58–$99 |
All components are Azure-native and fit within a standard enterprise Azure tenant. Entra ID SSO replaces the current password gate, and the full stack runs under $100 per month. → Full site guide