Skip to content

Uber

MetadataValue
Categorylogistics
Capabilitieshttp
Websitehttps://uber.com
  • order — from get_delivery, get_messages, add_to_cart, checkout, track_delivery
  • order[] — from list_deliveries, get_cart
  • place — from get_store
  • place[] — from search_address, list_addresses, search_stores, list_nearby_stores
  • product — from get_item_customizations
  • product[] — from search_products
  • trip — from get_trip
  • trip[] — from list_trips
  • web — Uber rider account — requires cookies from a logged-in browser session
  • eats — Uber Eats — requires cookies from a logged-in ubereats.com browser session

Ride history, trip details, receipts, and account info from Uber. Uses Uber’s internal GraphQL API at riders.uber.com/graphql via browser session cookies. Uber Eats uses a separate RPC API at ubereats.com/_p/api/.

Before extending this skill, read:

  1. Reverse Engineering overview — methodology, tools, progression
  2. Transport & Anti-Bot — TLS fingerprinting, WAF bypass, cookie domain filtering
  3. requirements.md — captured API shapes, endpoint inventory, auth headers
  4. Uber Eats E2E spec — the plan for what we’re building
  • list_trips — Ride history with pagination. Returns trip ID, destination, fare, date, and map URL. Supports profile_type (PERSONAL/BUSINESS) filter and pagination via next_page_token. Max 50 per page.
  • get_trip — Full trip details: driver info, pickup/dropoff addresses, fare breakdown, distance, duration, vehicle type, surge pricing, map URL, and rating.
  • whoami — Full user profile: name, email, phone, rating, picture URL, Uber One membership, payment methods, and profiles (personal/business).
  • check_session — Validate session cookies and return account identity.

Requires an active Uber session in Brave (or another browser). The skill extracts session cookies from the browser’s cookie database. No API keys needed.

  1. Log in to riders.uber.com in Brave
  2. Cookies are extracted automatically when you use the skill

Cookie auth against .uber.com. The rides API uses a single GraphQL endpoint:

POST https://riders.uber.com/graphql

IMPORTANT: Always use http.headers(waf="cf", accept="json", extra={...}) for all HTTP requests in this skill. The engine sets zero default headers — without http.headers(), you get no User-Agent, no sec-ch-, no Sec-Fetch- — and some Uber endpoints reject the request. We are acting as Brave, so always send what Brave sends. See docs/skills/sdk.md.

Rides-specific headers (pass via extra=):

  • x-csrf-token: x (literal string, not a real CSRF token)
  • x-uber-rv-session-type: desktop_session

Three GraphQL operations:

  • CurrentUserRidersWeb — user profile
  • Activities — trip history with filtering/pagination
  • GetTrip — full trip details with receipt

Uber has cookies on multiple subdomains (.uber.com, .riders.uber.com, .auth.uber.com). The engine’s RFC 6265 domain matching ensures only cookies matching riders.uber.com are sent. This prevents csid collisions from sibling subdomains that caused login redirects before domain filtering was implemented.

See Transport & Anti-Bot docs for details.

Uber Eats uses a completely different API from rides. It’s NOT GraphQL — it’s an RPC-style API at www.ubereats.com/_p/api/.

Used browse capture (CDP network capture via bin/browse-capture.py) to navigate ubereats.com/orders in Brave and capture all API calls. Key findings:

Uber Eats API endpoints (all POST https://www.ubereats.com/_p/api/):

EndpointPurposeRequest body
getPastOrdersV1Order history{ "lastWorkflowUUID": "" } (pagination)
getOrderEntitiesV1Order details — items, driver, receipt{}
getActiveOrdersV1Live orders in progress{ "orderUuid": null, "timezone": "America/Chicago" }
getCartsViewForEaterUuidV1Current cart state{}
getSearchHomeV2Store browsing / search{ "dropPastOrders": true }
getDraftOrdersByEaterUuidV1Draft (unsent) orders{ "removeAdapters": true }
getUserV1User profile for Eats{ "shouldGetSubsMetadata": true }
getProfilesForUserV1User profiles{}
getInstructionForLocationV1Delivery instructions{ "location": { "latitude": ..., "longitude": ... } }
setRobotEventsV1Bot detection telemetry{ "action": "rendered", "payload": { "isBot": false } }

Auth headers for Eats (different from rides):

x-csrf-token: x
x-uber-session-id: <from uev2.id.session cookie>
x-uber-target-location-latitude: 30.271044
x-uber-target-location-longitude: -97.695755
x-uber-client-gitref: <client version hash>
x-uber-ciid: <client instance ID>
x-uber-request-id: <UUID per request>
Content-Type: application/json

Cookie domain: .ubereats.com (NOT .uber.com — different domain from rides)

Real-time events: ramenphx/events/recv and ramendca/events/recv — likely SSE or long-polling for live delivery tracking updates.

Key difference from rides: The order_types: "EATS" parameter on the rides GraphQL Activities query does NOT work — EATS is not a valid enum value in RVWebCommonActivityOrderType. Uber Eats order history must be fetched from the Eats-specific getPastOrdersV1 endpoint.

See Uber Eats E2E spec for the full plan.

Phase 1 (read):

  • list_deliveries — Eats order history via getPastOrdersV1
  • get_delivery — Full delivery details: getReceiptByWorkflowUuidV1 for items (HTML parse with lxml), getPastOrdersV1 for metadata. Note: getOrderEntityByUuidV1 only works for active orders (404 for completed).
  • list_stores — Browse stores via getSearchHomeV2 or getFeedV1
  • get_menu — Store menu/items via getStoreV1 (not yet captured)

Phase 2 (tracking):

  • track_delivery — Live driver location via real-time events
  • list_messages — Driver communication

Phase 3 (write — requires firewall):

  • add_to_cart, checkout, approve_substitution, rate_delivery
  • agentos browse request uber — authenticated HTTP request with full header visibility. Used to verify cookie auth and inspect response headers.
  • agentos browse cookies uber — cookie inventory showing all .uber.com cookies with timestamps and provenance.
  • agentos browse auth uber — auth resolution trace showing which provider won (brave-browser) and identity (agentos@contini.co).
  • bin/browse-capture.py — CDP network capture. Connected to Brave via CDP, navigated to ubereats.com/orders, captured 90 requests including all /_p/api/ calls with full headers and POST bodies.

Step 1: Capture network traffic with CDP

Terminal window
# Launch Brave with CDP
open -a "Brave Browser" --args --remote-debugging-port=9222 --remote-allow-origins="*"
# Capture network traffic for any Uber Eats page
python3 bin/browse-capture.py https://www.ubereats.com/store/costco/... --port 9222
# Look for /_p/api/ POST requests in the output
# Response bodies are captured automatically via CDP Network.getResponseBody

Step 2: Extract full API surface from JS bundles

Don’t just capture what one page loads — extract ALL endpoint names from the client JS:

Terminal window
# Find the main bundle URL from browse-capture output
# Then grep for API endpoint patterns
curl -s "https://www.ubereats.com/_static/client-main-*.js" \
| grep -oE 'get[A-Z][a-zA-Z]+V[0-9]+' | sort -u # read endpoints
curl -s "https://www.ubereats.com/_static/client-main-*.js" \
| grep -oE '[a-z]+[A-Z][a-zA-Z]+V[0-9]+' | sort -u | grep -v '^get' # write endpoints

This revealed 32 endpoints (22 read, 10 write) that weren’t visible from a single page capture. The pattern {verb}{Entity}V{version} is consistent across all Uber Eats endpoints.

Step 3: Test individual endpoints

Use agentos browse request or direct curl to test specific endpoints. The auth headers and cookie domain are documented in requirements.md.

See Reverse Engineering overview for the full methodology and Browse Toolkit spec for tool documentation.

Making authenticated API calls via CDP:

import json, urllib.request, websocket
# Connect to Brave (must be running with --remote-debugging-port=9222)
tabs = json.loads(urllib.request.urlopen("http://127.0.0.1:9222/json").read())
ws = websocket.create_connection(tabs[0]["webSocketDebuggerUrl"], timeout=15)
# IMPORTANT: Navigate to ubereats.com first — fetch with credentials: 'include'
# only sends cookies for same-origin requests
ws.send(json.dumps({"id": 1, "method": "Page.navigate",
"params": {"url": "https://www.ubereats.com/"}}))
import time; time.sleep(5) # wait for page load
# Call any /_p/api/ endpoint
js = """
(async () => {
const r = await fetch('https://www.ubereats.com/_p/api/getPastOrdersV1', {
method: 'POST',
credentials: 'include',
headers: {'Content-Type': 'application/json', 'x-csrf-token': 'x'},
body: JSON.stringify({"lastWorkflowUUID": ""})
});
return await r.text();
})()
"""
ws.send(json.dumps({"id": 2, "method": "Runtime.evaluate",
"params": {"expression": js, "awaitPromise": True, "returnByValue": True}}))
# Read response (skip any navigation events)
for _ in range(20):
resp = json.loads(ws.recv())
if resp.get("id") == 2:
data = json.loads(resp["result"]["result"]["value"])
break

Key gotchas:

  • Use websocket module (installed), NOT websockets (not installed). Synchronous API, no asyncio.
  • Brave’s cookie DB is encrypted — can’t extract cookies from SQLite directly. Use CDP Network.getCookies or the agentOS engine’s auth resolver.
  • The x-csrf-token: x header is required. Other Eats headers (x-uber-session-id, x-uber-target-location-*) are optional for basic reads — the browser sends them automatically via cookies.
  • When reading CDP responses, check resp.get("id") to match your request — navigation and other events arrive on the same websocket.