gopuff.com logo
gopuff.com

place-order

Installation

Adds this website's skill for your agents

 

Summary

Build a GoPuff delivery order for a US address: set the delivery location, add products to the bag, and read back the priced bag (line items, quantities, estimated subtotal) and delivery ETA, stopping at GoPuff's mandatory sign-in gate. Read-only — never signs in, pays, or places the order.

FIG. 01
FIG. 02
FIG. 03
FIG. 04
FIG. 05
FIG. 06
FIG. 07
FIG. 08
SKILL.md
168 lines

Ordering from GoPuff

Purpose

Build a GoPuff delivery order for a given US delivery address: set the delivery location, find products in the location-scoped catalog, add them to the bag, and read back the priced bag (line items, quantities, estimated subtotal) plus the delivery ETA — stopping at GoPuff's mandatory sign-in gate. This skill is read-only. It never signs in, never enters payment, and never places the final order — GoPuff has no guest checkout, so completing a purchase requires an authenticated account and a saved payment method, which are out of scope. Treat this as "assemble a priced cart and report it up to the checkout wall."

When to Use

  • "How much would a bag of {items} cost from GoPuff delivered to {address}, and how fast?"
  • Price-checking specific GoPuff SKUs at a specific delivery address (pricing and availability are location-scoped).
  • Verifying that GoPuff delivers to an address and surfacing the delivery ETA.
  • Pre-staging a cart for a human to review before they sign in and pay.
  • NOT for: actually completing a purchase (requires account + payment; prohibited here), or order tracking after purchase.

Workflow

The only reliable surface is the browser. GoPuff is behind Kasada Monocle anti-bot; there is no usable public ordering API, and — critically — residential proxies make things worse (Kasada flags proxy/VPN egress IPs and serves "Monocle CAPTCHA Denied"). The working configuration is a --verified session with NO --proxies.

1. Create a verified (non-proxied) session

SID=$(browse cloud sessions create --keep-alive --verified \
  | node -e "let s='';process.stdin.on('data',c=>s+=c).on('end',()=>process.stdout.write(JSON.parse(s).id))")
export BROWSE_SESSION="$SID"

Do not add --proxies. A proxied session gets Monocle CAPTCHA Denied ("Please disconnect from any VPNs or proxies"). A bare (non-verified) session renders a blank/challenge page. Only --verified alone reliably passes.

2. Load the homepage and confirm you cleared Kasada

browse open "https://www.gopuff.com/" --remote
browse wait timeout 8000 --remote
browse get title --remote   # must be "Gopuff: 15-Min Delivery ..." — NOT "Just a moment..." or "Monocle CAPTCHA Denied"

If the title is a challenge string, the session config is wrong (see gotchas). Re-create with --verified and no proxies.

3. Set the delivery address (mandatory gate — no catalog/pricing/cart until this is done)

browse click "@<ref for 'Enter your address'>" --remote   # header button, text "ENTER YOUR ADDRESS"
browse wait timeout 2500 --remote                          # opens /add-new-address dialog
browse click "@<ref for textbox: Address>" --remote
browse type "1500 Market St, Philadelphia" --remote        # use `type`, NOT `fill` (fill submits early)
browse wait timeout 3000 --remote                          # Google Places suggestions render after ~3s
browse click "@<ref for the matching suggestion button>" --remote   # e.g. "1500 Market St Philadelphia, PA, USA"
browse wait timeout 2000 --remote                          # confirm view: map + Apt/Suite + Home/Work
browse click "@<ref for 'Save and Finish'>" --remote
browse wait timeout 5000 --remote

Success indicator: the catalog renders with a header showing ARRIVES IN N MINS and the street name (e.g. 1500 MARKET ST). The address is stored in session cookies for the rest of the flow.

4. Find products and add them to the bag

Two ways to reach a product:

  • Direct URL (fastest if you know the SKU): https://www.gopuff.com/p/{slug}/p{productId} — e.g. /p/coca-cola-12pk-12oz-can/p9697.
  • Search: click the textbox: Search ("Search Gopuff"), type a query, press Enter, and open a result link (same /p/{slug}/p{id} shape).

On the product page, read the heading: (product name) and the $X.XX price, then:

browse click "@<ref for 'Add to Bag'>" --remote
browse wait timeout 3000 --remote
# The header "MyBagButton" count increments (0 -> 1). Repeat for more items.

5. Open the bag and read the priced order

browse click "@<ref for 'MyBagButton'>" --remote   # opens the bag drawer
browse wait timeout 2000 --remote
browse click "@<ref for 'My Bag'>" --remote         # navigates to https://www.gopuff.com/bag
browse wait timeout 3000 --remote
browse snapshot --remote

The /bag page lists each line item (name, quantity, price), an Estimated Subtotal $X.XX, and a Checkout button. Extract these for the output.

6. Confirm the checkout gate and STOP

Clicking Checkout routes to https://www.gopuff.com/user-registration?from=bagRoot — a mandatory sign-in/sign-up wall (Continue with Google / Apple / Facebook, or phone/email). There is no guest checkout. Report checkout_state: "requires_signin" and stop. Do not authenticate, do not enter payment, do not place the order.

7. Release the session

browse cloud sessions update "$SID" --status REQUEST_RELEASE

Site-Specific Gotchas

  • READ-ONLY. Never sign in, never enter payment, never click a final "Place Order". A complete purchase is impossible without a GoPuff account + payment method and is out of scope for this skill.
  • Kasada Monocle anti-bot. GoPuff wraps every page in Kasada (MCL.configure, /validate_spur_captcha; challenge titles "Just a moment..." → "Monocle CAPTCHA Denied"). A bare Browserbase session renders a blank/challenge page.
  • --verified clears Kasada but is PROBABILISTIC — retry on denial. In testing, one verified session passed on first load; another identical verified session hit "Monocle CAPTCHA Denied" and only cleared after re-opening the URL and waiting ~12s (cleared by the 2nd–3rd attempt). If the title is "Monocle CAPTCHA Denied", do NOT give up: browse open the URL again + browse wait timeout 12000 and re-check the title, up to ~3 times, before recreating the session. Do not add proxies as a "fix" — that guarantees denial.
  • Proxies HURT — do not use --proxies. Kasada explicitly flags proxy/VPN egress IPs: a --verified --proxies session returns "Captcha validation failed. Please disconnect from any VPNs or proxies and try again." The observed egress IP on the proxied path was a datacenter IP that Kasada rejected. --verified alone (no proxies) is the only config that passed in testing. This is the opposite of most anti-bot sites — do not "escalate" to proxies here.
  • The host pre-run probe (Cloudflare/likelyNeedsProxies: true) is misleading for this site. The real wall is Kasada, and proxies make it fail. Trust the empirical result: verified, no proxies.
  • Address gate is mandatory and comes first. No product prices, catalog, or cart function until a deliverable address is set via the /add-new-address dialog. Pricing and product availability are location-scoped, so always set the address before reading any price.
  • Use browse type, not browse fill, in the address box. fill auto-submits and skips the Google Places typeahead; type then a ~3s wait lets the suggestion buttons render so you can click the matching one.
  • Address autocomplete is Google Places. Suggestions appear ~3s after typing; each is a button: whose accessible name is the full formatted address. Pick the one that matches; ignore business-name variants ("StrEATS of Philly...", "PIDC...").
  • Product URL pattern is stable: /p/{slug}/p{productId} (e.g. p9697). The numeric p{id} is the SKU; the slug is cosmetic. /near-me/{state}/{city} pages exist for SEO but the shoppable catalog is the location-gated app, not those pages.
  • Two-step bag open. MyBagButton opens a drawer; the My Bag button inside it navigates to the full /bag page where the Estimated Subtotal and Checkout button live.
  • Snapshots are large and hydrate slowly. Always browse wait timeout 3000–8000ms after any browse open on gopuff.com before snapshotting — Kasada clearance + React hydration take a few seconds. GoPuff a11y snapshots are big (~190KB); pipe them through grep for the refs/text you need rather than reading them whole. If browse snapshot appears to fail or truncate, fall back to browse get text body to confirm page state, then target elements by their accessible-name refs.
  • "Estimated" subtotal only. The /bag page shows an estimated subtotal (product prices, no markups/service fees per GoPuff's banner). Taxes, delivery fee, tip, and any promos are only computed after sign-in, which this skill does not reach — so the returned total is pre-tax/pre-fees.
  • No usable ordering API confirmed. All ordering happens through the Kasada-protected web app; there is no public JSON ordering endpoint to shortcut to. Don't waste time hunting for one.

Expected Output

// Primary success: cart assembled, priced, stopped at sign-in gate
{
  "success": true,
  "delivery_address": "1500 Market St, Philadelphia, PA, USA",
  "delivery_eta_minutes": 19,
  "bag": [
    { "name": "Coca-Cola 12pk 12oz Can", "product_url": "https://www.gopuff.com/p/coca-cola-12pk-12oz-can/p9697", "quantity": 1, "price": "$9.99" }
  ],
  "estimated_subtotal": "$9.99",
  "note": "Estimated subtotal is pre-tax and excludes delivery fee/tip, which are only computed after sign-in.",
  "checkout_state": "requires_signin",
  "error_reasoning": null
}

// Anti-bot wall (wrong session config — bare or proxied)
{
  "success": false,
  "checkout_state": null,
  "error_reasoning": "Kasada Monocle blocked the session ('Monocle CAPTCHA Denied'). Use a --verified session with NO --proxies."
}

// Address not serviceable (GoPuff does not deliver to the entered address)
{
  "success": false,
  "delivery_address": "<entered address>",
  "checkout_state": null,
  "error_reasoning": "Address is outside GoPuff's delivery zone — no catalog/ETA rendered after saving the address."
}