check-availability▌
recreation.gov/check-availability-3ldi81 · updated May 21, 2026
MDX-style export adds YAML metadata + attribution linking explainx.ai and this canonical listing URL.
Check live availability for any Recreation.gov bookable resource — campground, backcountry permit, lottery, timed-entry tour, day-use site — over a date range and return the per-site/per-division, per-day availability matrix with equipment, accessibility, pet policy, fees, and canonical URLs. Read-only.
| name | check-availability |
| title | Recreation.gov Availability Check |
| description | >- Check live availability for any Recreation.gov bookable resource — campground, backcountry permit, lottery, timed-entry tour, day-use site — over a date range and return the per-site/per-division, per-day availability matrix with equipment, accessibility, pet policy, fees, and canonical URLs. Read-only. |
| website | recreation.gov |
| category | outdoors |
| tags | - camping - permits - lottery - national-parks - availability - read-only |
| source | 'browserbase: agent-runtime 2026-05-18' |
| updated | '2026-05-18' |
| recommended_method | api |
| alternative_methods | - method: browser rationale: >- Fallback only. The React SPA at /camping/campgrounds/{id} renders the same data the JSON API exposes but costs ~1 MB JS download, ~3 s render, and virtualized calendar grids require scrolling — roughly 100x slower and dollar-costlier than the API. Reserve for hot-launch moments (Half Dome/Mt. Whitney lottery release) when Akamai gates the API; pair with --advanced-stealth --proxies. |
| verified | false |
| proxies | false |
Recreation.gov Availability Check
Purpose
Given a Recreation.gov bookable resource — campground, backcountry permit, lottery, timed-entry tour, or day-use site — plus a date range and an optional filter surface, return the per-site (or per-division) per-day availability matrix. Resolves names → facility IDs via Recreation.gov's public-but-undocumented JSON API, then pulls structured per-day status, equipment caps, accessibility, pet policy, fees, photos, and canonical site URLs.
Read-only — never click Reserve, Add to Cart, Add to Lottery, Apply, or Proceed to Payment.
When to Use
- "Is Upper Pines open for tents 6/15–6/19?" — campground availability lookups.
- "When does the Half Dome daily-permit lottery draw next, and how many slots remain post-draw?" — backcountry permit + lottery.
- "Any Wave Coyote Buttes North permits left in June 2026?" — daily-lottery + advanced-lottery permits.
- "Mariposa Grove shuttle tickets for next Saturday morning?" —
timedentry/timedentry_tourticketing. - Any scraper / agent that previously rendered the React SPA to read availability — replace with the JSON path below for a ~100× speed-up.
Workflow
Recreation.gov ships a public-but-undocumented JSON API that backs every page of the React SPA. There is no auth, no cookies, no CSRF token, and no anti-bot challenge on the read endpoints used below — verified against /api/search, /api/search/suggest, /api/camps/availability/campground/{id}/month, /api/camps/availability/campsite/{id}/all, /api/camps/campsites/{id}, /api/camps/campgrounds/{id}, /api/permits/{id}/availability, /api/permitcontent/{id}, and /api/timedentry/availability/facility/{id} (2026-05-18, no proxies, no stealth, no Referer, default browser-shaped UA — all returned 200 with full payload). Lead with the JSON path; only fall back to scripted browsing if Recreation.gov rolls anti-bot onto these endpoints (not observed today, but they reserve the right to gate hot-launch moments — see Gotchas).
Step 1 — Resolve the input to a typed entity_id
Skip if the caller already gave a /camping/campgrounds/{id}, /permits/{id}, or /ticket/facility/{id} URL — parse the trailing integer and the path segment, which maps directly to the entity_type used below:
| URL path | entity_type | Use availability endpoint in step 2 |
|---|---|---|
/camping/campgrounds/{id} | campground | A |
/permits/{id} | permit | B |
/ticket/facility/{id} | timedentry / timedentry_tour | C |
Otherwise resolve a free-text name (and optional state) through the suggest index:
GET https://www.recreation.gov/api/search/suggest?q={URL-encoded name}&geocoder=true
Returns inventory_suggestions[] with entity_id, entity_type, name, parent_name, state_code (full state name — "California", not "CA"), preview_image_url, and reservable: bool. Filter client-side on state if needed — the documented fq=state_code:"CA" filter on /api/search gets HTML-entity-encoded by the gateway and returns total: 0. Stick with suggest + client-side filter.
For permit/lottery lookups, the verbose /api/search?q=...&entity_type=permit endpoint returns richer cards (camping-equipment-allowed lists, average rating, accessible-campsite counts, mailing/physical addresses) — only call it when you actually need those extra fields. Both endpoints share the same entity_id namespace.
Step 2 — Pull availability based on entity_type
A. Campgrounds (entity_type: "campground")
Two endpoint shapes — pick by the shape of the question.
A1. "What's available across all sites in this campground for these dates?" — the per-facility, per-month endpoint:
GET https://www.recreation.gov/api/camps/availability/campground/{facilityId}/month
?start_date=YYYY-MM-01T00%3A00%3A00.000Z
start_datemust be the first of a month inYYYY-MM-01T00:00:00.000Zform. Any other day returns400 {"error":"Only the first of the month is allowed for this request"}. To cover a multi-month range, loop month-by-month and concatenatecampsites[*].availabilitieskeys.- Returns
{campsites: {{campsite_id}: {site, loop, campsite_type, campsite_reserve_type, availabilities: {date: status}, quantities, min_num_people, max_num_people, type_of_use}}, count}. Upper Pines (232447) returns 235 sites at ~490 KB per month. availabilities[date]values from this endpoint:"Available","Reserved","Closed","Not Reservable","Not Available","Open","Walk-up". Verified observed in this endpoint shape during sampling:Available, Reserved, Closed.
A2. "What are the next 18 months of availability for one specific site?" — the per-campsite endpoint:
GET https://www.recreation.gov/api/camps/availability/campsite/{campsiteId}/all
- Returns ~603 days of availability for one site (≈ 18 months forward from today). Cheaper than month-looping when you only care about one or a handful of sites.
- Status enum is DIFFERENT here: values observed are
"Open","Reserved","Closed","NYR"(Not Yet Released — the future booking window hasn't opened yet). Map"Open"→"Available"and"NYR"→"Not Reservable"when normalizing across both endpoints.
B. Permits / lotteries (entity_type: "permit")
GET https://www.recreation.gov/api/permits/{permitId}/availability
?start_date=YYYY-MM-DDT00%3A00%3A00.000Z
&end_date=YYYY-MM-DDT00%3A00%3A00.000Z
&commercial_acct=false
&is_lottery=false
- Returns
{payload: {permit_id, next_available_date, availability: {{division_id}: {date_availability: {date: {total, remaining, show_walkup, is_secret_quota}}}}}}. remainingis the post-lottery walk-up quota for daily-permit systems (Half Dome, Wave Daily).is_secret_quota: truemeans the API hides the exact number — surface asremaining: null, is_secret_quota: truerather than guessing.is_lottery=trueflips the response to lottery-draw quotas (pre-draw applied-count, lottery_close_date, lottery_draw_date) for advanced-lottery permits like Wave Advanced (274309) and Half Dome's Seasonal division.
Fetch division metadata (names like "Half Dome Cables (Daily)", "Scenic", "Educational", accessibility flags, entry/exit points, per-division fees) from /api/permitcontent/{permitId} — the payload.divisions map is keyed by the same division_id returned in the availability response. The same payload exposes has_lottery: bool, the lotteries[] array of past/current lottery instances (one with is_active: true, executed: false is the next draw), and important_dates[].
C. Tours / day-use timed entry (entity_type: "timedentry" or "timedentry_tour")
GET https://www.recreation.gov/api/timedentry/availability/facility/{facilityId}
?date=YYYY-MM-DD
- One date per request. Loop client-side for a range. Bare
YYYY-MM-DDonly — passingYYYY-MM-DDT00:00:00.000Zreturns400 {"error":"strconv.Atoi: parsing \"01T00:00:00.000Z\": invalid syntax"}. - Returns an array of tour-time slots with
inventory_count.{ANY,COMM,FIT,LOTTERY,WALKUP}and matchingreservation_count.*— available count =inventory_count.ANY−reservation_count.ANY. Also surfacesbooking_windows.PRIMARY.{open_timestamp, close_timestamp}(the visibility window relative to wall time) andbooking_window_open_overridewhen the agency has shifted the release time. - The legacy
/api/ticket/...paths in older docs return 404 or empty arrays — use/api/timedentry/....
Step 3 — Enrich with per-site metadata
For each campsite_id you decide to surface, hit:
GET https://www.recreation.gov/api/camps/campsites/{campsiteId}
Returns under campsite.*:
campsite_name(the public site number, e.g."040"),loop,campsite_type("RV NONELECTRIC","STANDARD NONELECTRIC","TENT ONLY NONELECTRIC", etc.),is_accessible(the ADA flag),permitted_equipment[](e.g.[{equipment_name: "RV", max_length: 20}, {equipment_name: "Pop up", max_length: 18}]) —max_lengthis in feet,attributes[]of{attribute_code, attribute_value}pairs — pullpets_allowed,max_num_people,max_num_vehicles,max_vehicle_length,driveway_length,site_length,site_details_map.{campfire_allowed, capacity_rating, checkin_time, checkout_time, ...}for the summary card,notices[]withnotice_type: "info" | "warning"— booking caveats the agency surfaces in the UI (HTML-escaped; un-escape<before display),campsite_latitude/campsite_longitudefor the map pin.
For facility-level metadata (the campground's name, address, phone, time zone, alternate_names, cancellation_description, attached links[] of photos):
GET https://www.recreation.gov/api/camps/campgrounds/{facilityId}
Step 4 — Apply caller-side filters
The API does not accept filter params on the availability endpoints — apply group_size / site_type / equipment / ADA / pet / loop filters by post-filtering the campsite list against the metadata in step 3.
| Caller filter | Post-filter predicate |
|---|---|
group_size: N | attributes.max_num_people >= N |
site_type: "Tent Only" | campsite_type startswith "TENT ONLY" |
rv_length_ft: L | any(eq.max_length >= L for eq in permitted_equipment if eq.equipment_name == "RV") |
electric: true | campsite_type does NOT end in "NONELECTRIC" (presence of "ELECTRIC", "FULL HOOKUP", or "FULL HOOKUP ELECTRIC") |
accessibility: true | is_accessible == true |
pets_allowed: true | attribute_code "pets_allowed" value != "None" |
loop: "Upper Pines" | loop == "Upper Pines" |
Step 5 — Construct canonical URLs
campground site: https://www.recreation.gov/camping/campsites/{campsite_id}
campground facility: https://www.recreation.gov/camping/campgrounds/{facility_id}
permit: https://www.recreation.gov/permits/{permit_id}
permit booking: https://www.recreation.gov/permits/{permit_id}/registration/detailed-availability?type=overnight-permit
tour / timedentry: https://www.recreation.gov/ticket/facility/{facility_id}
tour booking tour: https://www.recreation.gov/ticket/{facility_id}/ticket/{tour_id}
Browser fallback
The React SPA at /camping/campgrounds/{id} paints the same data the JSON path returns, but every read costs ~1 MB of JS download + ~3 s rendering, the calendar grid is virtualized (must scroll to materialize off-screen weeks), and per-site detail requires opening a modal per click. The JSON path is ~100× faster and dollar-cheaper. Only fall back if Recreation.gov starts gating the API endpoints (in which case: open a Browserbase session with --advanced-stealth --proxies because the JS bundle and /api/* calls then go through Akamai's challenge layer; the public read endpoints listed above do not require it today).
Site-Specific Gotchas
start_datemust be the 1st of a month on/api/camps/availability/campground/{id}/month. Server returns400 {"error":"Only the first of the month is allowed for this request"}for any other day. Multi-month range queries must loop month-by-month and concatenate.- The status enum differs between
/monthand/campsite/.../all./monthemitsAvailable | Reserved | Closed | Not Reservable | Not Available | Open | Walk-up./campsite/{id}/allemitsOpen | Reserved | Closed | NYR. Always normalize when merging the two:Open → Available,NYR → Not Reservable(the future booking window hasn't opened yet). A naïve consumer that only knowsAvailablewill treat valid future inventory as unavailable. - Tour / timedentry availability is one date per request.
/api/timedentry/availability/facility/{id}?date=YYYY-MM-DD— bare YYYY-MM-DD, no ISO suffix. Passing2026-06-01T00:00:00.000Zreturns400 strconv.Atoi parsing "01T00:00:00.000Z". The legacy/api/ticket/...paths return 404 or empty — they were superseded. is_lottery=truevsis_lottery=falseare different views of the same permit. False returns the post-draw walk-up quota stream (daily walk-up flag + remaining). True returns the pre-draw applied-count / lottery_close_date / lottery_draw_date. For permits with both (Half Dome: daily walk-up plus a separate seasonal lottery division), call both shapes and merge bydivision_id.is_secret_quota: truemeans the API hidesremaining. Don't inferremaining: 0— it's "the agency declines to publish the number." Surfaceremaining: null, is_secret_quota: true.reservable: falsein/api/search/suggest. Some entities (boundary-onlyrecareaentries, decommissioned facilities) come back withreservable: false— skip them before hitting any availability endpoint or you'll get an empty-payload 200./api/search?q=...&fq=state_code:"CA"is HTML-entity-encoded by the gateway: the response echoesfq:["state_code:"CA""]and silently returnstotal: 0. Either drop thefqand filter client-side onstate_code(which is the full state name, e.g."California", not the ISO code"CA"), or use/api/search/suggestwhich doesn't acceptfqat all./api/tours/{id}returns the React SPA HTML, not JSON. That route is a client-side React path, not an API. Use/api/timedentry/availability/facility/{id}for tour-shaped facilities.facility_id≠legacy_id≠parent_asset_id≠campsite_id. The/api/searchresults exposeentity_id(which is thefacility_idfor campgrounds, thepermit_idfor permits, and thefacility_idfor tours). Inside a campground response, each site has its owncampsite_id(the URL-segment for/camping/campsites/{id}) plus alegacy_idused by older Park-Service systems. The two are not interchangeable in URLs.- HTML-escaped notice text.
campsite.notices[].notice_textcontains literal<p>/<strong>— un-escape before surfacing or you'll show raw entities. - Rate-limiting is not enforced today but the agency reserves the right at launch moments. The Half Dome / Mt. Whitney / Wave lottery-window opening (15th of each month at 07:00 PT for Yosemite Valley campgrounds, mid-Feb for Mt. Whitney, etc.) historically triggers Akamai 503s and a CAPTCHA wall on
/api/*. For real-time monitoring during a hot launch, switch to a Browserbase session with--advanced-stealth --proxiesand back off on 429/503. state_codein suggest results is the full state name./api/search/suggestreturnsstate_code: "California", but/api/camps/campgrounds/{id}and/api/searchreturnstate: "CA". Don't equality-match across the two responses without normalizing.- Sites in a campground have heterogeneous reserve types.
campsite_reserve_typecan be"Site-Specific"(book exact site),"Non Site-Specific"(book a site class, get one assigned at check-in), or"Group"/"Walk-Up Only". Surfaces in both the per-month and the per-site responses. - READ-ONLY. Never POST to
/api/reservations/*,/api/order/*,/api/permits/{id}/registration/*, or/api/timedentry/orders/*. Never clickReserve,Add to Cart,Add to Lottery,Apply,Proceed to Paymentif you fall back to the browser.
Expected Output
Three distinct outcome shapes — campground, permit, tour.
// Campground — per-site, per-day matrix
{
"kind": "campground",
"facility_id": "232447",
"facility_name": "Upper Pines Campground",
"parent_recarea": "Yosemite National Park",
"state": "CA",
"facility_url": "https://www.recreation.gov/camping/campgrounds/232447",
"checkin": "2026-06-15",
"checkout": "2026-06-19",
"filters_applied": {"site_type": "TENT ONLY", "group_size": 4, "pets_allowed": true},
"sites_total": 235,
"sites_after_filter": 71,
"sites": [
{
"campsite_id": "98",
"site_number": "040",
"loop": "Upper Pines",
"campsite_type": "RV NONELECTRIC",
"reserve_type": "Site-Specific",
"max_num_people": 6,
"max_num_vehicles": 2,
"is_accessible": false,
"pets_allowed": "Domestic",
"permitted_equipment": [
{"equipment_name": "RV", "max_length_ft": 20},
{"equipment_name": "Pop up", "max_length_ft": 18}
],
"lat": 37.73751, "lon": -119.56544,
"availability": {
"2026-06-15": "Available",
"2026-06-16": "Available",
"2026-06-17": "Reserved",
"2026-06-18": "Available"
},
"nightly_price_usd": null,
"fees_breakdown": [{"label": "Peak", "amount_usd": 36.00}],
"site_url": "https://www.recreation.gov/camping/campsites/98"
}
]
}
// Permit / lottery — per-division, per-day quota
{
"kind": "permit",
"permit_id": "234652",
"permit_name": "Half Dome Permits",
"has_lottery": true,
"lottery_state": {
"active_lottery_id": "0d1b1413-57c2-4701-acf1-f0b227f7e58e",
"is_active": true,
"executed": false,
"draw_at": "2026-03-15T00:00:00Z",
"applications_close_at": "2026-03-01T23:59:59Z"
},
"divisions": [
{
"division_id": "31",
"division_name": "Half Dome Cables (Daily)",
"type": "Entry Point",
"is_accessible": false,
"is_lottery_option": false,
"per_date": [
{"date": "2026-06-01", "total_quota": 275, "remaining": 81, "show_walkup": false, "is_secret_quota": false},
{"date": "2026-06-02", "total_quota": 275, "remaining": 62, "show_walkup": false, "is_secret_quota": false}
]
}
],
"permit_url": "https://www.recreation.gov/permits/234652"
}
// Tour / timed-entry — per-slot for one date
{
"kind": "timedentry_tour",
"facility_id": "10112471",
"facility_name": "Mariposa Grove Commercial Bus Parking",
"date": "2026-06-01",
"booking_window": {
"primary_opens_at": "2026-05-02T08:00:00-07:00",
"primary_closes_at": "2026-06-01T08:00:00-07:00"
},
"slots": [
{
"tour_time": "08:00",
"inventory_total": 1,
"available": 0,
"reservation_count": 1,
"is_secondary_window_only": false
}
],
"facility_url": "https://www.recreation.gov/ticket/facility/10112471"
}
How to use check-availability on Cursor
AI-first code editor with Composer
Prerequisites
Before installing skills in Cursor, ensure your development environment meets these requirements:
- ›Cursor installed and configured on your development machine
- ›Node.js version 16.0+ with npm package manager (verify with
node --version) - ›Active project directory or workspace where you want to add check-availability
Execute installation command
Execute the skills CLI command in your project's root directory to begin installation:
The skills CLI fetches check-availability from GitHub repository recreation.gov/check-availability-3ldi81 and configures it for Cursor.
Select Cursor when prompted
The CLI will show a list of available agents. Use arrow keys to navigate and space to select Cursor:
Verify installation
Confirm successful installation by checking the skill directory location:
Reload or restart Cursor to activate check-availability. Access the skill through slash commands (e.g., /check-availability) or your agent's skill management interface.
Security & Verification Notice
We perform automated surface-level scans (Gen AI Scanner, Socket, Snyk) during installation. These checks detect common vulnerabilities but do not guarantee complete security. Always review skill source code and verify the publisher's reputation before production use.
Skills execute code in your development environment. Always verify the publisher's identity, review recent commits, and test in isolated environments before production deployment.
List & Monetize Your Skill
Submit your Claude Code skill and start earning
Use Cases▌
Task Automation & Efficiency
Automate repetitive workflows and reduce manual effort
Example
Generate reports, summarize documents, draft communications
Save 3-5 hours per week on routine tasks
Knowledge Enhancement
Learn new skills, understand complex topics, get expert guidance
Example
Explain concepts, provide examples, suggest learning resources
Accelerate learning and skill development by 2x
Quality Improvement
Enhance output quality through reviews, suggestions, and refinements
Example
Review drafts, suggest improvements, catch errors
Improve work quality by 30-40% with less effort
Implementation Guide▌
Prerequisites
- ›Claude Desktop or compatible AI client with skill support
- ›Clear understanding of task or problem to solve
- ›Willingness to iterate and refine outputs
Time Estimate
15-45 minutes depending on use case complexity
Installation Steps
- 1.Install skill using provided installation command
- 2.Test with simple use case relevant to your work
- 3.Evaluate output quality and relevance
- 4.Iterate on prompts to improve results
- 5.Integrate into regular workflow if valuable
Common Pitfalls
- ⚠Expecting perfect results without iteration
- ⚠Not providing enough context in prompts
- ⚠Using skill for tasks outside its intended scope
- ⚠Accepting outputs without review and validation
Best Practices▌
✓ Do
- +Start with clear, specific prompts
- +Provide relevant context and constraints
- +Review and refine all outputs before using
- +Iterate to improve output quality
- +Document successful prompt patterns
✗ Don't
- −Don't use without understanding skill limitations
- −Don't skip validation of outputs
- −Don't share sensitive information in prompts
- −Don't expect skill to replace human judgment
💡 Pro Tips
- ★Be specific about desired format and style
- ★Ask for multiple options to choose from
- ★Request explanations to understand reasoning
- ★Combine AI efficiency with human expertise
When to Use This▌
✓ Use When
Use when skill capabilities match your task, clear ROI on time saved, and you can validate outputs. Best for repetitive tasks, learning, and quality improvement.
✗ Avoid When
Avoid when task requires deep expertise you can't validate, involves sensitive decisions, or when learning process is more valuable than speed of completion.
Learning Path▌
- 1Familiarize yourself with skill capabilities and limitations
- 2Start with low-risk, non-critical tasks
- 3Progress to more complex and valuable use cases
- 4Build expertise through regular use and experimentation
Discussion
Product Hunt–style comments (not star reviews)- No comments yet — start the thread.
Ratings
4.6★★★★★30 reviews- ★★★★★Sofia Kim· Dec 28, 2024
check-availability has been reliable in day-to-day use. Documentation quality is above average for community skills.
- ★★★★★Shikha Mishra· Dec 24, 2024
check-availability reduced setup friction for our internal harness; good balance of opinion and flexibility.
- ★★★★★Mei Rahman· Dec 24, 2024
check-availability reduced setup friction for our internal harness; good balance of opinion and flexibility.
- ★★★★★Aisha Harris· Nov 23, 2024
Keeps context tight: check-availability is the kind of skill you can hand to a new teammate without a long onboarding doc.
- ★★★★★Lucas Singh· Nov 19, 2024
check-availability fits our agent workflows well — practical, well scoped, and easy to wire into existing repos.
- ★★★★★Rahul Santra· Nov 15, 2024
I recommend check-availability for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
- ★★★★★Li Jain· Nov 15, 2024
I recommend check-availability for anyone iterating fast on agent tooling; clear intent and a small, reviewable surface area.
- ★★★★★Olivia White· Oct 14, 2024
check-availability is among the better-maintained entries we tried; worth keeping pinned for repeat workflows.
- ★★★★★Isabella Martinez· Oct 10, 2024
We added check-availability from the explainx registry; install was straightforward and the SKILL.md answered most questions upfront.
- ★★★★★Pratham Ware· Oct 6, 2024
Useful defaults in check-availability — fewer surprises than typical one-off scripts, and it plays nicely with `npx skills` flows.
showing 1-10 of 30