Skip to content

Repository files navigation

Flight Watcher Agent

A small Python agent that runs on a Mac, checks Google Flights results through SerpApi, filters the trip against your rules, and sends a Gmail alert every time it runs.

The default configuration watches:

  • Austin, Texas (AUS) to Punta Cana, Dominican Republic (PUJ)
  • Departure date: 2026-07-03
  • Return date: 2026-07-08
  • 2 adults and 2 children, ages 4 and 5
  • Maximum 1 stop each way
  • Outbound departure before noon
  • Return arrival before 10 PM
  • Maximum total price from MAX_TOTAL_PRICE
  • Optional layover-duration filtering

The project stores credentials in a local .env file. Do not commit .env.

Requirements

  • macOS
  • Python 3
  • A SerpApi account and API key
  • A Gmail account with a Gmail app password

Install

git clone https://github.com/evelita17/flight-watcher-agent.git
cd flight-watcher-agent
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env

Edit .env with your own values.

Configure Trip Rules

Example .env:

SERPAPI_API_KEY=your_serpapi_key
SERPAPI_NO_CACHE=0

DEPARTURE_ID=AUS
ARRIVAL_ID=PUJ
OUTBOUND_DATE=2026-07-03
RETURN_DATE=2026-07-08
ADULTS=2
CHILDREN=2
CHILD_AGES=4,5
CURRENCY=USD

MAX_TOTAL_PRICE=2200
MAX_STOPS=1
MAX_LAYOVER_MINUTES=180
IGNORE_LAYOVER_TIME=1
OUTBOUND_DEPART_BEFORE_HOUR=12
RETURN_ARRIVE_BY_HOUR=22

GMAIL_ADDRESS=your_gmail@gmail.com
GMAIL_APP_PASSWORD=your_16_character_app_password
ALERT_TO=your_destination_email@example.com
ALERT_REPEAT_MATCHES=0

Notes:

  • DEPARTURE_ID and ARRIVAL_ID are airport codes.
  • Dates use YYYY-MM-DD.
  • MAX_TOTAL_PRICE is the total trip price limit in the configured currency.
  • IGNORE_LAYOVER_TIME=1 disables layover-duration filtering.
  • IGNORE_LAYOVER_TIME=0 uses MAX_LAYOVER_MINUTES.
  • OUTBOUND_DEPART_BEFORE_HOUR=12 means outbound flights must leave before noon.
  • RETURN_ARRIVE_BY_HOUR=22 means return flights must arrive before 10 PM.
  • ALERT_REPEAT_MATCHES=0 avoids repeated emails for the exact same found deal.
  • No-results status emails are sent every run.

Get a SerpApi Key

This project uses SerpApi's Google Flights API. It does not use an official Google Flights API key, because Google does not provide a simple public Google Flights booking-search API for this use case.

  1. Create or sign in to a SerpApi account at serpapi.com.
  2. Open the SerpApi API key page: serpapi.com/manage-api-key.
  3. Copy your private API key.
  4. Put it in .env:
SERPAPI_API_KEY=your_serpapi_key

SerpApi documents that api_key is the private key used to authenticate requests and that it is available in your account/API key area. See SerpApi Account API and SerpApi status/error docs.

Set Up Gmail Email Sending

The agent sends through Gmail SMTP using:

  • Host: smtp.gmail.com
  • Port: 587
  • Security: STARTTLS

You must use a Gmail app password. Do not use your normal Gmail login password.

  1. Open Google Account Security.
  2. Turn on 2-Step Verification.
  3. Open Google App Passwords.
  4. Create an app password for Mail or another custom app name.
  5. Copy the 16-character app password.
  6. Add it to .env:
GMAIL_ADDRESS=your_gmail@gmail.com
GMAIL_APP_PASSWORD=your_16_character_app_password
ALERT_TO=where_to_send_alerts@example.com

Google's help page explains that app passwords require 2-Step Verification and are intended for apps or devices that cannot use "Sign in with Google": Sign in with app passwords.

Run Once

Dry run: searches flights and prints the email body, but does not send email or mark deals as emailed.

. .venv/bin/activate
python flight_watcher.py --once --dry-run

Real run: searches flights and sends either a found-deal email or a no-results email.

. .venv/bin/activate
python flight_watcher.py --once

Run Continuously in the Foreground

This keeps a Python process open and checks every 30 minutes by default:

. .venv/bin/activate
python flight_watcher.py

Set a different interval:

python flight_watcher.py --interval-minutes 60

Schedule Hourly on macOS

The repo includes a LaunchAgent installer. It creates:

~/Library/LaunchAgents/com.evelyn.flight-watcher.plist

The schedule uses StartInterval=3600, so it runs once when loaded and then once per hour while the Mac is awake and the user session is active.

Install the schedule:

chmod +x install_launch_agent.sh run_flight_watcher.sh
./install_launch_agent.sh

Load/start it:

launchctl bootstrap gui/$(id -u) ~/Library/LaunchAgents/com.evelyn.flight-watcher.plist
launchctl kickstart -k gui/$(id -u)/com.evelyn.flight-watcher

Check status:

launchctl print gui/$(id -u)/com.evelyn.flight-watcher

View logs:

tail -f logs/flight-watcher.log
tail -f logs/flight-watcher.err.log

Stop/unload it:

launchctl bootout gui/$(id -u) ~/Library/LaunchAgents/com.evelyn.flight-watcher.plist

Older macOS versions may also accept:

launchctl load ~/Library/LaunchAgents/com.evelyn.flight-watcher.plist
launchctl unload ~/Library/LaunchAgents/com.evelyn.flight-watcher.plist

Keep the Mac Awake

LaunchAgent jobs do not run while the Mac is fully asleep. If you want hourly checks to keep running, keep the Mac plugged in and awake.

On macOS Monterey:

  1. Apple menu -> System Preferences -> Battery.
  2. Choose Power Adapter.
  3. Enable "Prevent your Mac from automatically sleeping when the display is off."
  4. Optionally enable "Wake for network access."

Terminal option:

caffeinate -s

Keep that terminal open. Stop it with Control+C.

Files

  • flight_watcher.py - the flight-search and email agent
  • run_flight_watcher.sh - wrapper used by launchd
  • install_launch_agent.sh - creates the hourly macOS LaunchAgent plist
  • requirements.txt - Python dependencies
  • .env.example - safe example configuration
  • .gitignore - excludes .env, virtualenvs, logs, caches, and state

Security Notes

  • Never commit .env.
  • Never commit SerpApi keys, Gmail app passwords, or personal passwords.
  • If a key or password is accidentally published, rotate it immediately.
  • The agent intentionally keeps sent-deal state in .state/sent_flights.json, which is ignored by git.

Provider Notes

Flight websites change frequently and direct scraping can be blocked or violate terms. This agent uses SerpApi as a structured flight-search provider instead of scraping browser pages directly.

About

this agent checks with serpAPI for flights

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages