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:

  1. Click “New Agent”. Name it traveldroid.
  2. Select the Node 22 runtime.
  3. Attach Telegram and Gmail connectors.
  4. 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.js with ctx.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:

  1. 24 h before departure, trigger a cron (exact to the second)
  2. Launch Puppeteer, log in, smash the check-in button
  3. 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/terminal fields.
  • 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.