Book restaurant reservations via browser automation
Restaurant booking

Book restaurant reservations via browser automation. Use when asked to make dinner reservations, book a table, or find availability at restaurants.
---
name: restaurant-booking
description: Book restaurant reservations via browser automation. Use when asked to make dinner reservations, book a table, or find availability at restaurants. Supports OpenTable, Resy, and direct restaurant booking sites.
source: orthogonal
---
# Restaurant Booking
## Setup
Read your credentials from ~/.gooseworks/credentials.json:
```bash
export GOOSEWORKS_API_KEY=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json'))['api_key'])")
export GOOSEWORKS_API_BASE=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json')).get('api_base','https://api.gooseworks.ai'))")
```
If ~/.gooseworks/credentials.json does not exist, tell the user to run: `npx gooseworks login`Overview
If ~/.gooseworks/credentials.json does not exist, tell the user to run: npx gooseworks login
Manual install (npx, ZIP)
npx skills add gooseworks-ai/goose-skills --skill restaurant-booking -g -a claude-codemkdir -p ~/.claude/skills && curl -sL https://codeload.github.com/gooseworks-ai/goose-skills/tar.gz/615c685f34f8 \
| tar -xz -C ~/.claude/skills --strip-components=4 goose-skills-615c685f34f8/skills/research-tools/capabilities/restaurant-bookingNew-Item -ItemType Directory -Force "$HOME\.claude\skills" | Out-Null; Invoke-WebRequest "https://m.agentalley.io/zip/246b7de0f7a03c7003e9/restaurant-booking.zip" -OutFile "$env:TEMP\restaurant-booking.zip"; Expand-Archive "$env:TEMP\restaurant-booking.zip" -DestinationPath "$HOME\.claude\skills" -ForceConnects with Agent Alley MCP · agentalley.io/mcp
Files included
SKILL.md6.7 KBskill.meta.json291 B
Read the files here
gooseworks-ai/
Show the full text221 lines
Restaurant Booking
Setup
Read your credentials from ~/.gooseworks/credentials.json:
export GOOSEWORKS_API_KEY=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json'))['api_key'])")
export GOOSEWORKS_API_BASE=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json')).get('api_base','https://api.gooseworks.ai'))")
If ~/.gooseworks/credentials.json does not exist, tell the user to run: npx gooseworks login
All endpoints use Bearer auth: -H "Authorization: Bearer $GOOSEWORKS_API_KEY"
Book reservations using Notte browser automation via Orthogonal.
Requirements
- Orthogonal CLI (
npm install -g @orth/cli) or API key - Guest info: name, email, phone
Quick Flow
- Start Notte session
- Navigate to booking site (OpenTable preferred)
- Select date/time/party size
- Fill contact form
- Submit and confirm
CLI Method (Recommended)
1. Start a Notte Session
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/start"}'
--body '{"browser_type":"chromium","headless":true,"solve_captchas":true,"idle_timeout_minutes":10}'
Save the session_id from the response.
2. Navigate to OpenTable
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"goto","url":"https://www.opentable.com/r/{restaurant}?datetime=2026-02-17T19:00&covers=2"}'
3. Click Time Slot
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"click","selector":"button:has-text(\"7:00 PM\")"}'
4. Select Seating (if prompted)
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"click","selector":"button:has-text(\"Select\")"}'
5. Fill the Form
# First name
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"fill","selector":"input#firstName","value":"John"}'
# Last name
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"fill","selector":"input#lastName","value":"Doe"}'
# Email
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"fill","selector":"input#email","value":"[email protected]"}'
# Phone
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"fill","selector":"input#phoneNumber","value":"4155551234"}'
6. Accept Terms
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"click","selector":"text=I agree to the restaurant"}'
7. Submit Reservation
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}'
--body '{"type":"click","selector":"button:has-text(\"Complete reservation\")"}'
8. Verify Confirmation
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"notte","path":"/sessions/{session_id}/page/scrape"}'
--body '{"only_main_content":true}'
Look for "confirmed" in the response.
API Method (curl)
# Start session
curl -X POST "https://api.orth.sh/v1/run" \
-H "Content-Type: application/json" \
-d '{
"api": "notte",
"path": "/sessions/start",
"body": {
"browser_type": "chromium",
"headless": true,
"solve_captchas": true,
"idle_timeout_minutes": 10
}
}'
# Execute actions (same pattern)
curl -X POST "https://api.orth.sh/v1/run" \
-H "Content-Type: application/json" \
-d '{
"api": "notte",
"path": "/sessions/{session_id}/page/execute",
"body": {"type":"goto","url":"https://www.opentable.com/..."}
}'
Key Selectors (OpenTable)
| Field | Selector |
|---|---|
| First name | input#firstName |
| Last name | input#lastName |
input#email |
|
| Phone | input#phoneNumber |
| Terms checkbox | text=I agree to the restaurant |
| Submit | button:has-text('Complete reservation') |
| Time slots | button:has-text('7:00 PM') |
| Seating select | button:has-text('Select') |
Finding Restaurant IDs
Search OpenTable and extract from URL:
restref=1906→ Foreign Cinema- Restaurant slug in URL path
Example URL format:
https://www.opentable.com/r/{restaurant-slug}?restref={id}&datetime={YYYY-MM-DDTHH:MM}&covers={n}
Tips
- OpenTable holds table for 5 minutes - move fast
- Use
fillaction withvalueparam (nottypewithtext) - Click terms via label text, not checkbox directly
- No credit card needed - reservations are free
- Confirmation email sent automatically
Resy Alternative
If restaurant uses Resy:
https://resy.com/cities/{city}/venues/{restaurant}?date={YYYY-MM-DD}&seats={n}
Similar flow but different selectors. Scrape page first to identify form fields.
After Booking
- Create calendar event with
gog calendar create - Add attendees and location
- Include confirmation number in description
| 1 | |
| 2 | name restaurant-booking |
| 3 | description Book restaurant reservations via browser automation. Use when asked to make dinner reservations, book a table, or find availability at restaurants. Supports OpenTable, Resy, and direct restaurant booking sites. |
| 4 | source orthogonal |
| 5 | |
| 6 | |
| 7 | |
| 8 | # Restaurant Booking |
| 9 | |
| 10 | ## Setup |
| 11 | |
| 12 | Read your credentials from ~/.gooseworks/credentials.json: |
| 13 | |
| 14 | export GOOSEWORKS_API_KEY=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json'))['api_key'])") |
| 15 | export GOOSEWORKS_API_BASE=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json')).get('api_base','https://api.gooseworks.ai'))") |
| 16 | |
| 17 | |
| 18 | If ~/.gooseworks/credentials.json does not exist, tell the user to run: `npx gooseworks login` |
| 19 | |
| 20 | All endpoints use Bearer auth: `-H "Authorization: Bearer $GOOSEWORKS_API_KEY"` |
| 21 | |
| 22 | |
| 23 | Book reservations using Notte browser automation via Orthogonal. |
| 24 | |
| 25 | ## Requirements |
| 26 | |
| 27 | Orthogonal CLI (`npm install -g @orth/cli`) or API key |
| 28 | Guest info: name, email, phone |
| 29 | |
| 30 | ## Quick Flow |
| 31 | |
| 32 | Start Notte session |
| 33 | Navigate to booking site (OpenTable preferred) |
| 34 | Select date/time/party size |
| 35 | Fill contact form |
| 36 | Submit and confirm |
| 37 | |
| 38 | ## CLI Method (Recommended) |
| 39 | |
| 40 | ### 1. Start a Notte Session |
| 41 | |
| 42 | |
| 43 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 44 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 45 | -H "Content-Type: application/json" \ |
| 46 | -d '{"api":"notte","path":"/sessions/start"}' |
| 47 | --body '{"browser_type":"chromium","headless":true,"solve_captchas":true,"idle_timeout_minutes":10}' |
| 48 | |
| 49 | |
| 50 | Save the `session_id` from the response. |
| 51 | |
| 52 | ### 2. Navigate to OpenTable |
| 53 | |
| 54 | |
| 55 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 56 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 57 | -H "Content-Type: application/json" \ |
| 58 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 59 | --body '{"type":"goto","url":"https://www.opentable.com/r/{restaurant}?datetime=2026-02-17T19:00&covers=2"}' |
| 60 | |
| 61 | |
| 62 | ### 3. Click Time Slot |
| 63 | |
| 64 | |
| 65 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 66 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 67 | -H "Content-Type: application/json" \ |
| 68 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 69 | --body '{"type":"click","selector":"button:has-text(\"7:00 PM\")"}' |
| 70 | |
| 71 | |
| 72 | ### 4. Select Seating (if prompted) |
| 73 | |
| 74 | |
| 75 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 76 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 77 | -H "Content-Type: application/json" \ |
| 78 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 79 | --body '{"type":"click","selector":"button:has-text(\"Select\")"}' |
| 80 | |
| 81 | |
| 82 | ### 5. Fill the Form |
| 83 | |
| 84 | |
| 85 | # First name |
| 86 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 87 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 88 | -H "Content-Type: application/json" \ |
| 89 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 90 | --body '{"type":"fill","selector":"input#firstName","value":"John"}' |
| 91 | |
| 92 | # Last name |
| 93 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 94 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 95 | -H "Content-Type: application/json" \ |
| 96 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 97 | --body '{"type":"fill","selector":"input#lastName","value":"Doe"}' |
| 98 | |
| 99 | |
| 100 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 101 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 102 | -H "Content-Type: application/json" \ |
| 103 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 104 | --body '{"type":"fill","selector":"input#email","value":"[email protected]"}' |
| 105 | |
| 106 | # Phone |
| 107 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 108 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 109 | -H "Content-Type: application/json" \ |
| 110 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 111 | --body '{"type":"fill","selector":"input#phoneNumber","value":"4155551234"}' |
| 112 | |
| 113 | |
| 114 | ### 6. Accept Terms |
| 115 | |
| 116 | |
| 117 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 118 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 119 | -H "Content-Type: application/json" \ |
| 120 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 121 | --body '{"type":"click","selector":"text=I agree to the restaurant"}' |
| 122 | |
| 123 | |
| 124 | ### 7. Submit Reservation |
| 125 | |
| 126 | |
| 127 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 128 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 129 | -H "Content-Type: application/json" \ |
| 130 | -d '{"api":"notte","path":"/sessions/{session_id}/page/execute"}' |
| 131 | --body '{"type":"click","selector":"button:has-text(\"Complete reservation\")"}' |
| 132 | |
| 133 | |
| 134 | ### 8. Verify Confirmation |
| 135 | |
| 136 | |
| 137 | curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \ |
| 138 | -H "Authorization: Bearer $GOOSEWORKS_API_KEY" \ |
| 139 | -H "Content-Type: application/json" \ |
| 140 | -d '{"api":"notte","path":"/sessions/{session_id}/page/scrape"}' |
| 141 | --body '{"only_main_content":true}' |
| 142 | |
| 143 | |
| 144 | Look for "confirmed" in the response. |
| 145 | |
| 146 | ## API Method (curl) |
| 147 | |
| 148 | |
| 149 | # Start session |
| 150 | curl -X POST "https://api.orth.sh/v1/run" \ |
| 151 | |
| 152 | -H "Content-Type: application/json" \ |
| 153 | -d '{ |
| 154 | "api": "notte", |
| 155 | "path": "/sessions/start", |
| 156 | "body": { |
| 157 | "browser_type": "chromium", |
| 158 | "headless": true, |
| 159 | "solve_captchas": true, |
| 160 | "idle_timeout_minutes": 10 |
| 161 | } |
| 162 | }' |
| 163 | |
| 164 | # Execute actions (same pattern) |
| 165 | curl -X POST "https://api.orth.sh/v1/run" \ |
| 166 | |
| 167 | -H "Content-Type: application/json" \ |
| 168 | -d '{ |
| 169 | "api": "notte", |
| 170 | "path": "/sessions/{session_id}/page/execute", |
| 171 | "body": {"type":"goto","url":"https://www.opentable.com/..."} |
| 172 | }' |
| 173 | |
| 174 | |
| 175 | ## Key Selectors (OpenTable) |
| 176 | |
| 177 | | Field | Selector | |
| 178 | |-------|----------| |
| 179 | | First name | `input#firstName` | |
| 180 | | Last name | `input#lastName` | |
| 181 | | Email | `input#email` | |
| 182 | | Phone | `input#phoneNumber` | |
| 183 | | Terms checkbox | `text=I agree to the restaurant` | |
| 184 | | Submit | `button:has-text('Complete reservation')` | |
| 185 | | Time slots | `button:has-text('7:00 PM')` | |
| 186 | | Seating select | `button:has-text('Select')` | |
| 187 | |
| 188 | ## Finding Restaurant IDs |
| 189 | |
| 190 | Search OpenTable and extract from URL: |
| 191 | `restref=1906` → Foreign Cinema |
| 192 | Restaurant slug in URL path |
| 193 | |
| 194 | Example URL format: |
| 195 | |
| 196 | https://www.opentable.com/r/{restaurant-slug}?restref={id}&datetime={YYYY-MM-DDTHH:MM}&covers={n} |
| 197 | |
| 198 | |
| 199 | ## Tips |
| 200 | |
| 201 | OpenTable holds table for 5 minutes - move fast |
| 202 | Use `fill` action with `value` param (not `type` with `text`) |
| 203 | Click terms via label text, not checkbox directly |
| 204 | No credit card needed - reservations are free |
| 205 | Confirmation email sent automatically |
| 206 | |
| 207 | ## Resy Alternative |
| 208 | |
| 209 | If restaurant uses Resy: |
| 210 | |
| 211 | https://resy.com/cities/{city}/venues/{restaurant}?date={YYYY-MM-DD}&seats={n} |
| 212 | |
| 213 | |
| 214 | Similar flow but different selectors. Scrape page first to identify form fields. |
| 215 | |
| 216 | ## After Booking |
| 217 | |
| 218 | Create calendar event with `gog calendar create` |
| 219 | Add attendees and location |
| 220 | Include confirmation number in description |
| 221 |
Details
- Updated
- Sep 21, 2026
- License
- MIT
- Stars on the repo
- ★ 1,220
- Checked
- Source
- gooseworks-ai/goose-skills ↗
- Creator
- gooseworks-ai · 206 listings
Made with restaurant-booking

Similar skills
See all →
SkillWeb browser automation with AI-optimized snapshotsBrowser Automation Skill
SkillDeepEval evaluation workflow for AI agents
SkillBrowser automation with persistent named pagesDev browser
SkillTurn visible project context, a proven thread, skillTurn into app
SkillComplete browser automation with PlaywrightPlaywright Browser Automation
SkillUse TinyFish for web search, fetching URLs, reading pagesTinyFish CLIMore from gooseworks-ai
SkillMine the highest-converting ad angles from customer reviewsAd angle miner
SkillAnalyze ad campaign performance data to identify what'sAd campaign analyzer
SkillFor paid lead-gen and participant-recruitment adsAd lead quality analyzer
SkillAnalyze the message match between your ads and landing pagesAd to landing page auditor
SkillCheck and improve your brand's visibility across AI searchAeo
SkillSearch Amazon products - find items, compare pricesAmazon Product Search