If you landed here you probably typed something like “OpenClaw flight booking and travel automation setup” into a search bar. Good. This page is exactly that: a step-by-step log of how I wired OpenClaw into my travel workflow—searching multiple airlines, tracking prices, booking with one click, auto-checking in the second the window opens, and pinging me on Signal when a gate changes.
Why bother automating travel with OpenClaw?
I fly 30-40 segments a year. The two things that regularly eat time are:
- Refreshing five airline sites because no single API covers every regional carrier.
- Remembering check-in windows—especially the 24 h minus one second Southwest boarding lottery.
OpenClaw already had browser control, scheduled tasks, and integrations with Telegram, Gmail, and iMessage. The community recently added @flightsearch-cli (multi-provider scraping wrapper around Skyscanner, Kiwi, Southwest, and United) which made the rest trivial.
This article walks through the exact versions and config I used: Node 22.4, OpenClaw 0.9.7, flightsearch-cli 1.2.3, Puppeteer 22, and a hosted Chromium browser on ClawCloud’s medium-gpu tier.
Prerequisites and high-level architecture
Accounts & keys
- ClawCloud account (free tier is enough)
- Telegram bot token (or Slack webhook—swap where noted)
- Optional: Twilio SMS key if you want boarding passes by text
Node & OpenClaw install
Locally or on ClawCloud:
# Node 22+ is mandatory for top-level await
$ nvm install 22.4
$ npm i -g openclaw@0.9.7
# Verify
$ claw --version
claw 0.9.7
Flight search CLI
$ npm i -g @openclaw-community/flightsearch-cli@1.2.3
$ flightsearch --help
That last command should list 12 providers. If you only see four you probably hit the “partial build” bug; reinstall with --force.
Putting the pieces together
The diagram in my head looks like this:
- Daemon — keeps the agent alive; runs cron-like schedules
- Gateway — web UI for logs, memory, and manual triggers
- Agent script — orchestrates search, price monitor, booking, and alerts
- Browser worker — Puppeteer session that lives only during check-in or booking
Factory-reset: creating a clean agent
From the ClawCloud dashboard:
- Click “New Agent”. Name it
traveldroid. - Select the Node 22 runtime.
- Attach Telegram and Gmail connectors.
- Skip the template chooser—we’re starting blank.
You land in the gateway at https://app.claw.run/traveldroid. The left nav shows “Memory”, “Schedule”, and “Logs”. The right side is an embedded Monaco editor backed by Git. Commit history matters because you will screw up at 2 AM finding that cheap JFK-LIS.
Section 1 – Flight search across multiple providers
Minimal search command
$ flightsearch JFK LIS 2024-11-14 --max-price 500 --json > search.json
That works interactively but we want an agent flow. Inside the gateway editor create scripts/search.js:
import { execSync } from 'node:child_process';
import fs from 'node:fs';
export async function run(ctx) {
const cmd = `flightsearch ${ctx.from} ${ctx.to} ${ctx.date} --max-price ${ctx.maxPrice} --json`;
const raw = execSync(cmd, { encoding: 'utf8' });
const results = JSON.parse(raw);
ctx.memory.set(`search-${ctx.date}`, results); // Persist for later steps
return results;
}
Why not a real API? Because airlines. Some offer REST but hide saver inventory; others block you after 30 requests. The CLI rotates IPs via the community’s proxy pool. It’s brittle, but it works. Trade-off accepted.
Scheduling daily scans
Open the “Schedule” tab, add:
cron: "0 2 * * *" # 02:00 UTC daily
script: scripts/search.js
vars:
from: JFK
to: LIS
date: 2024-11-14
maxPrice: 500
On every run the agent dumps the JSON into memory and emits a structured log. We’ll listen for deltas in the next section.
Section 2 – Price monitoring with memory diffs
Price alerts are basically a diff of yesterday vs today. Add scripts/monitor.js:
export async function run(ctx) {
const key = `search-${ctx.date}`;
const latest = ctx.memory.get(key);
const previous = ctx.memory.get(`${key}-prev`);
if (!previous) {
ctx.memory.set(`${key}-prev`, latest);
return 'First run, baseline stored.';
}
const drops = latest.filter(l => {
const p = previous.find(p => p.flightId === l.flightId);
return p && l.price < p.price;
});
if (drops.length) {
await ctx.telegram.sendMessage(ctx.userChat,
`✈️ Price drop on ${drops.length} flights to ${ctx.to}. Lowest now $${drops[0].price}`);
}
ctx.memory.set(`${key}-prev`, latest);
return `${drops.length} drops notified.`;
}
Hook it right after the search job:
cron: "5 2 * * *" # 5 min after search
script: scripts/monitor.js
vars:
date: 2024-11-14
to: LIS
userChat: 12345678
Test with Run Now. Telegram pings instantly. Rate limit on ClawCloud free tier is 20 messages/min so no danger of spamming yourself.
Section 3 – Assisted booking (semi-automated)
Full auto-purchase is technically possible—Puppeteer can fill card forms—but I keep a human in the loop because fraud rules vary per airline. The trick is to pre-fill everything up to the purchase confirm screen and hand over.
Storing passenger profiles
Add to agent memory under key profile-me:
- Name:
John Hackerman - DOB:
1984-04-01 - Passport:
P1234567 - Credit card last4:
4242
Now scripts/book.js:
import puppeteer from 'puppeteer';
export async function run(ctx) {
const { flightUrl } = ctx; // passed from Telegram deep link
const profile = ctx.memory.get('profile-me');
const browser = await puppeteer.launch({ headless: true });
const page = await browser.newPage();
await page.goto(flightUrl);
// Example selectors, adjust per airline
await page.type('#firstName', profile.name.split(' ')[0]);
await page.type('#lastName', profile.name.split(' ')[1]);
await page.type('#dob', profile.dob);
// ... other fields
// Stop before payment
const screenshot = await page.screenshot({ encoding: 'base64' });
await ctx.telegram.sendPhoto(ctx.userChat, screenshot, {
caption: 'Pre-filled, ready for card details.'
});
await browser.close();
}
The deep-link trick:
- User receives price-drop alert containing
/book?url=... - OpenClaw parses Telegram command, calls
book.jswithctx.flightUrl
Latency from click to screenshot: ~15 s on the medium-gpu tier. Acceptable.
Section 4 – The killer feature: automatic check-in
This part alone saves me boarding group agony. The flow:
- 24 h before departure, trigger a cron (exact to the second)
- Launch Puppeteer, log in, smash the check-in button
- Download boarding pass PDF, email + message it
Capturing login cookies once
Most airlines flag bot-like logins. Easiest workaround is a one-time manual login through the browser worker, then persist cookies in agent memory. Run this locally with --no-headless so you can solve captchas.
const browser = await puppeteer.launch({ headless: false });
const page = await browser.newPage();
await page.goto('https://www.southwest.com/');
// manual login...
const cookies = await page.cookies();
ctx.memory.set('southwest-cookies', cookies);
await browser.close();
The actual auto-check-in script
import puppeteer from 'puppeteer';
export async function run(ctx) {
const cookies = ctx.memory.get('southwest-cookies');
const browser = await puppeteer.launch({ args: ['--no-sandbox'] });
const page = await browser.newPage();
await page.setCookie(...cookies);
await page.goto('https://www.southwest.com/air/check-in/index.html');
await page.type('#confirmationNumber', ctx.conf);
await page.type('#firstName', ctx.first);
await page.type('#lastName', ctx.last);
await page.click('#form-mixin--submit-button');
await page.waitForSelector('.boarding-position', { timeout: 15000 });
const pos = await page.$eval('.boarding-position', el => el.textContent.trim());
const pdf = await page.pdf({ format: 'A4' });
await ctx.gmail.send({
to: ctx.email,
subject: `Checked in: ${pos}`,
attachments: [{ filename: 'boardingpass.pdf', content: pdf }]
});
await ctx.telegram.sendMessage(ctx.userChat, `Checked in! Position ${pos}`);
await browser.close();
}
Schedule dynamically per flight:
# in scripts/add-flight.js (called when you forward itinerary email)
const depTime = new Date(ctx.depUtc);
const checkin = new Date(depTime.getTime() - 24*3600*1000 + 1000); // +1s safety
ctx.scheduler.add({
runAt: checkin.toISOString(),
script: 'scripts/auto-checkin.js',
vars: { ...flightData }
});
The internal scheduler guarantees millisecond accuracy because it stores tasks in SQLite and polls with setTimeout. Verified over 20 flights—never missed the window.
Section 5 – Itinerary management and real-time alerts
OpenClaw’s persistent memory is basically Redis under the hood. I parse confirmation emails via Gmail webhooks, slap them into memory under trip:{conf}, and fire two other jobs:
- Gate watcher — hits aviationstack API every 5 min, compares
gate/terminalfields. - Delay notifier — same feed but filters
status === "delayed".
Sample gate watcher:
export async function run(ctx) {
const flight = ctx.memory.get(`trip:${ctx.conf}`);
const res = await fetch(`https://api.aviationstack.com/v1/flights?access_key=${ctx.key}&flight_iata=${flight.iata}`);
const data = (await res.json()).data[0];
if (data.gate && data.gate !== flight.gate) {
await ctx.telegram.sendMessage(ctx.userChat,
`Gate change for ${flight.iata}: ${flight.gate} → ${data.gate}`);
flight.gate = data.gate;
ctx.memory.set(`trip:${ctx.conf}`, flight);
}
}
This has saved me twice at ATL where Delta likes to flip gates 15 min before boarding.
Section 6 – Putting it all together locally vs ClawCloud
Running on your laptop
- Pro: free, full browser access, easier cookie capture
- Con: needs to stay online; macOS sleep killed my check-in once
Running on ClawCloud
- Pro: 99.9 % uptime SLA, managed Puppeteer images with GPU accel, one-click logs
- Con: headless only unless you pay for the interactive debug addon
I moved everything to ClawCloud after the sleep incident. Cost: about $4/month on the medium-gpu tier for 25 flights.
Section 7 – Hard edges, rate limits, and future work
- Airlines rotate HTML weekly. Keep selectors in a separate file and push fixes fast.
- Proxy pool has a 1 k requests/day cap. Long-haul city pairs hit that quick; stash results.
- Puppeteer PDF generation sometimes crashes on ARM. ClawCloud runs x86, you’re safe.
- I still manually enter card CVV—PCI rules aside, Captcha pops randomly.
- Community wants to swap aviationstack for the free Cirium beta. PRs welcome.
Next steps: your turn
Clone the repo snapshot below, push to your own ClawCloud agent, and schedule a dummy flight to test alerts. Worst case you learn some Puppeteer; best case you never fight for Southwest A-board again.
$ git clone https://github.com/youruser/openclaw-travel-kit
$ cd openclaw-travel-kit
$ claw push --agent traveldroid
Questions or improvements? Open an issue on GitHub or ping @steinberger in the Discord. Safe flights.