Lines 133-173markdown
133`browserless_agent` call carrying `proxy: { proxy: "residential" }` (the site sits behind
134Akamai — `akamai_visit_id` cookie is set on first response, and bare sessions get
135challenged). Keep all steps in **one** call's `commands` array so cookies/session persist:
1371. `{ "method": "goto", "params": { "url": "https://www.vaccines.gov/en/", "waitUntil": "load", "timeout": 45000 } }`
1382. `{ "method": "type", "params": { "selector": "<zip input>", "text": "10001" } }`, then `{ "method": "click", "params": { "selector": "<search button>" } }`
1393. **Do not use `networkidle`** — it hangs on this SPA. The Places call resolves in ~500ms but the React render lags ~3s, so wait explicitly: `{ "method": "waitForTimeout", "params": { "time": 4000 } }` (or `{ "method": "waitForSelector", "params": { "selector": "<card selector>", "timeout": 10000 } }`).
1404. `{ "method": "text", "params": { "selector": "body" } }` (or fold parsing into an `{ "method": "evaluate", ... }`) — pharmacy cards render as `<h3>{name}</h3>` + `<address>{address}</address>` + `<a href="https://www.google.com/maps/dir/?api=1...">Directions</a>` + `<a href="{websiteUri}">Website</a>`
1415. Filter + emit as above
143You can reconfirm the exact `places.googleapis.com/v1/places:searchText` request shape /
144API key by reading it via an `evaluate` in the browserless session or by inspecting that
145session's network — useful if the bundle hash changes (re-scrape the `AIza` key from
146`/_next/static/chunks/app/[locale]/results/page-*.js` if it 403s).
148## Site-Specific Gotchas
150- **Vaccines.gov is now a pharmacy directory, not a vaccine finder.** As of mid-2024 the site shed its appointment-finder backend (formerly powered by Castlight VaccineFinder) and re-launched as a Google-Places-backed pharmacy locator. The home page literally banners: _"The functionality of this website may be impacted while it is being updated."_ Do not promise users slot times from this surface.
151- **No vaccine-type input.** The UI accepts only ZIP. The request body sent to Google has `textQuery: "pharmacy zip code {zip}"` — vaccine type is _not_ in the query string and `includedType` is the constant `"pharmacy"`. Filtering by vaccine type is the consuming agent's job, downstream of this skill.
152- **No date input either.** Same reason. Slot windows are a downstream concern.
153- **Hard-coded Google API key in the bundle.** `AIzaSyCVvG6ZXIlxy76PCbqGnf9cP37XtA3HE-M` is shipped in plaintext in `/_next/static/chunks/app/[locale]/results/page-*.js` (bundle hash may rotate; if your stored key 403s, re-fetch the results-page chunk and grep `AIza`). Restrictions on the key are referer-based — sending the request from an arbitrary IP without a `Referer: https://www.vaccines.gov/` header may be rejected; mirror the browser referer when calling directly.
HighSecret Pattern
Google API key in build/src/skills/sites/vaccines.gov/find-appointment-55bu87/SKILL.md
build/src/skills/sites/vaccines.gov/find-appointment-55bu87/SKILL.mdView on unpkg · L153 154- **50-result cap.** The vaccines.gov UI iterates page-tokens at most 3× and stops when accumulated results reach 50 (`o.length < 50 && c < 3` in the bundle). To exceed 50, tile the bounding box into sub-rectangles and call separately — Google Places will not return more from a single rectangle even with further `pageToken` chasing.
155- **`includedType: "pharmacy"` + `strictTypeFiltering: true`** excludes urgent-care clinics, doctor offices, and grocery stores that _also_ carry pharmacies. To capture supermarket-embedded pharmacies (Kroger, Publix, Wegmans), relax to `strictTypeFiltering: false` and post-filter on `addressComponents` or `displayName.text`.
156- **Akamai gate, but soft.** The `www.vaccines.gov` HTML response sets `akamai_visit_id` / `Akamai-Request-ID` cookies. Bare-session fetches still succeed for HTML and `/_next/static/*` chunks (verified 2026-05-18). Stealth is _not_ required to read the page or hit the Places API; reserve the residential-proxy `browserless_agent` session for the browser fallback only.
157- **Page is fully client-rendered.** Server-rendered HTML for both `/en/` and `/en/results/?zip=...` contains only a title and shell — no pharmacy data is in the initial HTML. A plain HTTP fetch of the results URL will not return any pharmacy info; you must either (a) call Google Places directly (recommended), or (b) drive the browser to allow client-side hydration.
158- **Costco is a dead-end for booking.** `costco.com/pharmacy.html` has no online scheduler. Return the phone number; do not waste turns trying to find slots.
159- **Walgreens requires sign-in before slots.** A direct fetch of `walgreens.com/findcare/vaccination/our-services` (verified 2026-05-18) lands on a sign-in wall. The downstream `walgreens.com/schedule-vaccine` skill must carry credentials or a persisted browser context.
160- **Don't trust the inner-agent hallucination of "VTrckS / VAMS / CDC provider registry".** Models trained on pre-2024 data describe vaccines.gov as a CDC-backed inventory federation. That is no longer true. The actual data plane is **one** Google Places `searchText` call, period.
161- **No appointment slot data exists on vaccines.gov in any surface** — not via the HTML, not via any internal API, not via the Places response. Confirmed by JS-bundle inspection: the only outbound API call from the results page is to `places.googleapis.com`, and the field mask requested does not include any vaccine, schedule, or inventory field. Future agents: do not waste iterations trying to discover a hidden slot API. There is none.
169 "slot_data_available": false,
170 "next_step": "Dispatch each pharmacy to its chain's scheduler skill — vaccines.gov does not surface slot times.",
173 "place_id": "ChIJxxxxxxxxxxxxxxxxxxxxxxxx",