Google Flights Scraper: Daily Fares for a List of Routes
ProxyField's Web Scraping API is in development (Contact sales) and is designed to fetch Google Flights search pages with JS rendering for $2.00 per 1,000 successful results, or $1.00 from 10,000 results in one purchase. Google Flights has no public API. For alerts on a few routes, its own "Track prices" emails you when a tracked fare changes, for set dates or "Any dates", but it gives you no daily table. For a daily table of many routes, send each route's search URL once a day from the market you price and read the fares from the rendered page: 50 routes checked daily are 1,500 pages a month, $3, and 100 routes are $6. The same routine runs today in your own browser on ProxyField residential proxies (the Playwright script below): start with the Easy Trial, 1 GB for $2.95.
Through the sales team on our 24/7 live chat
| Fetch | Entry | Volume, from |
|---|---|---|
| HTTP | $0.50 | $0.20 |
| JS rendering | $2.00 | $1.00 |
Billed on successful results only.
Is there an official Google Flights API?
No. Google closed its QPX Express flight search API on April 10, 2018 (ITA Software on Wikipedia) and has offered no public flight search API since; its travel partner programs serve airlines and agencies that send their fares to Google, not people who want to read them. So a daily fare table from Google Flights means reading its public pages, by hand or with a scraper.
Four ways to collect daily fares
| You need | Use | What you get | Cost |
|---|---|---|---|
| Alerts on a few routes | Google Flights' own "Track prices", signed in to a Google account (Google's help page) | An email when a tracked fare changes; no table of prices | Nothing |
| One airline's or a booking system's fares | Airline and travel-industry APIs such as Amadeus, Sabre or Duffel, with partner access | The seller's own fares, not what Google Flights shows | Set by each program |
| Parsed Google Flights JSON | A scraper-API vendor's Google Flights endpoint | Fields as JSON, priced per search by the vendor | Set by each vendor |
| A daily table for many routes, as travelers in one market see them | The ProxyField Web Scraping API (access through Contact sales), or your own browser on residential proxies | The rendered page per route and date; the script below turns it into one CSV row per route | $2.00 per 1,000 pages, $1.00 from 10,000 |
For a few personal routes, Google's alerts are enough. For a dataset you query, keep a fixed search per route and store each check with its time, as below.
Collect daily fares for a list of routes
The daily routine, in five steps:
-
Fix one search per route market (
gland the exit IP's country), currency, passengers, cabin, one-way or return. A change in the fare is then a change in the price, not in the search. -
Once a day, send each route's search URL with JS rendering and wait for the flight rows.
-
Read each row's label with an
evaluatestep and keep the lowest fare, with its airline and stops. -
Append one CSV row per route (time of the check, route, date, lowest fare, currency, airline, stops, market, flights read, billed) and save the raw page to
pages/<date>/<route>.html. -
If a row shows 0 flights read, fix
ROWorLABELand re-parse that day's saved pages withreparse.pybelow, without fetching again.
Read moreShow less
Google Flights gives each flight row a label for screen readers. The script assumes the form "From 512 US dollars… Nonstop flight with …" and reads those labels rather than every dollar amount on the page (bag fees and price graphs carry dollar amounts too). The pattern is an assumption to check on a live page before the first run: Google changes its markup, and the saved pages let you fix the parser afterwards.
# daily_fares.py: the request the Web Scraping API takes (access through Contact sales)
import csv, pathlib, re, requests
from datetime import datetime, timezone
from urllib.parse import quote
API_KEY = "<api_key>"
MARKET = "us" # point of sale: exit IP country and gl
ROUTES = [("JFK", "LHR", "2026-12-10"), ("LAX", "NRT", "2026-12-15"), ("ORD", "CDG", "2027-01-08")]
ROW = '[aria-label^="From "]' # one flight row; check on a live page
LABEL = re.compile(r"From ([\d,]+) US dollars.*?(Nonstop|\d+ stops?) flight with ([^.]+)\.")
now = datetime.now(timezone.utc)
pages = pathlib.Path("pages", now.strftime("%Y-%m-%d"))
pages.mkdir(parents=True, exist_ok=True)
with open("fares.csv", "a", newline="") as f:
out = csv.writer(f)
for origin, dest, day in ROUTES:
trip = f"Flights to {dest} from {origin} on {day} oneway"
url = f"https://www.google.com/travel/flights?q={quote(trip)}&hl=en&gl={MARKET}&curr=USD"
r = requests.post("https://api.proxyfield.io/v1/scrape",
headers={"Authorization": f"Bearer {API_KEY}"},
json={"url": url, "render": True, "country": MARKET, "output": "json",
"actions": [
{"type": "wait_for", "selector": ROW, "timeout_ms": 30000},
{"type": "evaluate", "script":
f"Array.from(document.querySelectorAll('{ROW}'), e => e.getAttribute('aria-label'))"}]},
timeout=180)
if not r.ok: # error responses are not billed
out.writerow([now.isoformat(timespec="seconds"), origin, dest, day, "", "", "", "", MARKET, 0, "error " + str(r.status_code)])
continue
data = r.json()
(pages / f"{origin}-{dest}-{day}.html").write_text(data["content"] or "")
labels = data["actions_log"][-1].get("result") or []
flights = [(int(m[1].replace(",", "")), m[3].strip(), m[2]) for m in map(LABEL.search, labels) if m]
fare, airline, stops = min(flights) if flights else ("", "", "")
out.writerow([now.isoformat(timespec="seconds"), origin, dest, day, fare, "USD", airline, stops,
MARKET, len(flights), data["metadata"]["billed"]])Run it every morning with cron (crontab -e):
0 6 * * * cd /opt/fares && /usr/bin/python3 daily_fares.pyWhat one run leaves behind (columns: checked_at, origin, destination, date, fare, currency, airline, stops, market, flights read, billed). The row below is an illustration of the format with made-up values, not a real fare:
fares.csv: 2026-12-01T06:00:41+00:00,JFK,LHR,2026-12-10,512,USD,Example Air,Nonstop,us,14,True
pages/2026-12-01/JFK-LHR-2026-12-10.htmlStep 5, re-parse a day's saved pages without new requests (python3 reparse.py 2026-12-01):
# reparse.py: read the fares again from saved pages
import html, pathlib, re, sys
LABEL = re.compile(r"From ([\d,]+) US dollars.*?(Nonstop|\d+ stops?) flight with ([^.]+)\.")
for page in sorted(pathlib.Path("pages", sys.argv[1]).glob("*.html")):
labels = [html.unescape(a) for a in re.findall(r'aria-label="(From [^"]+)"', page.read_text())]
flights = [(int(m[1].replace(",", "")), m[3].strip(), m[2]) for m in map(LABEL.search, labels) if m]
print(page.stem, min(flights) if flights else "no flights read: adjust LABEL")What to expect:
- Keep the search fixed. The same market, currency, passengers and cabin every day, so a change in the fare is a change in the price, not in the search.
- An empty fare with
flights readat 0 means the label did not match: open that day's saved page, adjustROWorLABEL, and re-parse the saved pages without fetching again. - More dates per route, fewer pages: the date grid and price graph show the lowest fare for many days on one page; fetch single-date searches only for the dates you need in detail.
What the API takes and returns
Google Flights builds its results with scripts, so send its URLs with JS rendering on. The API takes a POST to https://api.proxyfield.io/v1/scrape with your API key in an Authorization: Bearer <api_key> header and a JSON body: url, render (true for JS rendering, false for plain HTTP), country and output (html, markdown, text or json). With rendering, wait_for takes a CSS selector the page must show before it comes back, and actions runs up to 20 browser steps (click, scroll, wait_for, evaluate and others); an evaluate step's return value comes back in actions_log[].result. Parameter reference: API documentation.
# The request the Web Scraping API takes (access through Contact sales)
curl https://api.proxyfield.io/v1/scrape \
-H "Authorization: Bearer <api_key>" \
-H "Content-Type: application/json" \
-d '{"url": "https://www.google.com/travel/flights?q=Flights%20to%20LHR%20from%20JFK%20on%202026-12-10%20oneway&hl=en&gl=us&curr=USD", "render": true, "country": "us", "output": "json"}'Example response (shortened; content is the rendered page's HTML):
{
"metadata": {"id": "req_f004eb639349981a", "api": "web_scrape", "status": "success", "billed": true},
"status_code": 200,
"final_url": "https://www.google.com/travel/flights?q=Flights%20to%20LHR%20from%20JFK%20on%202026-12-10%20oneway&hl=en&gl=us&curr=USD",
"content_type": "text/html; charset=utf-8",
"content": "<!doctype html><html lang=\"en\">…</html>",
"actions_log": []
}| Choice | Price per 1,000 successful results | Use it for |
|---|---|---|
| JS rendering | $2.00, $1.00 from 10,000 results in one purchase | Flight results, date grids, price graphs and booking options |
| Plain HTTP | $0.50, $0.20 from 10,000 results in one purchase | Airline and agency pages you follow from the booking options, where they need no scripts |
Pricing: $2.00 per 1,000 Google Flights pages, from $1.00
Google Flights pages cost the Web Scraping API's JS rendering price: $2.00 per 1,000 successful results, or $1.00 from 10,000 successful results in one purchase. One route checked once a day costs $0.06 a month and $0.73 a year (365 pages); 50 routes daily are 1,500 pages a month, $3.
Billed: a page Google answered with a 2xx status. Not billed: blocked requests, timeouts and errors on our side; a blocked request is retried on new IPs, and the retries are not billed. Every response says whether it was billed. A target's 404 or 410, and a sign-in page the site serves with a 200 status, count as billed results.
"–": below 10,000 results in one purchase, so the entry price applies.
Payment and balance: the same crypto balance as proxies, which never expires; there is no subscription or monthly fee. For availability and access, contact sales through the sales team on our 24/7 live chat. All prices: pricing.
Through the sales team on our 24/7 live chat
| Workload | Results | JS rendering at $2.00 | JS rendering at $1.00 (from 10,000 results in one purchase) |
|---|---|---|---|
| 1 route, daily, for a year | 365 | $0.73 | – |
| 50 routes, one date-grid page each, daily (30-day month) | 1,500 | $3 | – |
| 100 routes, one date-grid page each, daily (30-day month) | 3,000 | $6 | – |
| 20 routes × 90 departure dates, weekly (4 runs a month) | 7,200 | $14.40 | – |
| 50 routes × 60 departure dates, daily (30-day month) | 90,000 | $180 | $90 |
Why one route shows many fares
Google Flights shows fares for a market: the country in gl and of the visitor's IP sets the point of sale, curr the currency, and the fares sold there can differ from another country's. Fares also move with the dates, the number of passengers, the cabin and the time of the search. To collect what travelers in one market see, send the search from that country: ProxyField residential proxies offer targeting by country, region (state) and city, with 412M+ residential IPs in 195+ countries, for example the United Kingdom or Germany. The pool is clean for Google, checked and segmented. In a Web Scraping API request, country sets the country the request comes from (the exit IP), as a two-letter code such as de; it accepts the proxy pool's 195+ countries.
Google Flights data on public pages
Google Flights compares fares that airlines and online travel agencies sell for a route and a date, and anyone can search it without signing in. Price tracking and saved trips need a Google account and are out of scope.
| Part of the page | What it shows |
|---|---|
| Flight results | Airline, departure and arrival times, duration, stops and layover airports, fare, the "best" flights first |
| Price insights | Whether today's fares are low, typical or high for the route, and a price history where shown |
| Date grid and price graph | The lowest fare for each departure and return date around your dates |
| Booking options | Which airlines and agencies sell the chosen flight, and at what price |
| Flight details | Aircraft, legroom and amenities where shown, and an emissions estimate |
| Explore map | Destinations from an airport with their lowest fares for flexible dates |
A search URL can carry the trip as text, for example https://www.google.com/travel/flights?q=Flights%20to%20LHR%20from%20JFK%20on%202026-12-10%20oneway, plus hl for the language, gl for the country and curr for the currency.
Why Google Flights blocks scrapers
Google answers automated traffic with an "unusual traffic" page, a challenge or empty results: many searches from one IP, datacenter ranges and clients that do not run the page's scripts meet it first. With your own scraper, use a headless browser, rotate residential IPs, keep a few seconds between searches per IP and fix hl, gl and curr in every search. Running Google searches from many places more generally: Google proxies. Error codes explained: errors.
Scrape Google Flights with Python and ProxyField proxies
This script opens one Google Flights search in a real browser through a residential IP in New York and prints the flight rows it reads, the same labels the daily script parses. It runs today on residential proxies.
from urllib.parse import quote
from playwright.sync_api import sync_playwright
ROW = '[aria-label^="From "]' # one flight row; check on a live page
trip = "Flights to LHR from JFK on 2026-12-10 oneway"
URL = f"https://www.google.com/travel/flights?q={quote(trip)}&hl=en&gl=us&curr=USD"
with sync_playwright() as p:
browser = p.chromium.launch(proxy={
"server": "http://gate.proxyfield.io:7000",
"username": "<login>-country-us-city-new_york-session-fl01-ttl-600",
"password": "<password>"})
page = browser.new_page(locale="en-US")
page.goto(URL, timeout=90_000)
page.wait_for_selector(ROW, timeout=30_000)
for label in page.eval_on_selector_all(ROW, "rows => rows.map(r => r.getAttribute('aria-label'))")[:10]:
print(label[:120])
browser.close()The username keeps one IP for 10 minutes (-session-fl01-ttl-600), so the search and the scripts it loads come from the same address. Access opens once the payment is confirmed; the gateway, credentials or allowlist are in your account. Username parts after the login are optional: -country-<cc>, -region-<region>, -city-<city>, -session-<id> and -ttl-<seconds> (30 to 129,600 seconds, 20 minutes by default), as in <login>-country-us-region-new_york-city-new_york-session-he9f2qga-ttl-600. Residential proxies cost $2.95/GB for 1 GB and from $1.95/GB at volume, with unlimited concurrent threads; the traffic never expires, and all purchases are final. More on browser automation: Playwright.
What teams use Google Flights data for
- Fare monitoring price history per route, date and market, and alerts when fares drop.
- Airline revenue research how a carrier's fares compare with competitors' on the same routes.
- Travel startups deal feeds and flexible-date tools built on public fares.
- Corporate travel typical fares on frequent routes, to set travel budgets.
Booking, holding seats or reselling fares through a scraper is not data collection; fraud and fake accounts are forbidden under ProxyField's acceptable use policy.
Legal questions
Google's Terms of Service restrict automated access to its services, and Google Flights is one of them; the fares themselves come from airlines and agencies, whose terms may restrict reuse as well. Collect public fares only, keep personal data out, and read Is It Legal to Scrape Google? and Is Web Scraping Legal? US, EU and UK Rules (2026).
ProxyField's acceptable use policy allows collecting public web data and price monitoring, and forbids accessing data behind logins you are not entitled to. ProxyField's rule for every site: public pages only, and follow the site's terms. This is not legal advice.
More scrapers
- Flight and hotel scraper Skyscanner, Kayak, Momondo, Booking.com and other travel sites on the same API.
- Airline fare scraper fares from airline and agency sites.
- Expedia scraper fares from airline and agency sites.
- Hotel price scraper room rates across booking sites.
- Google SERP API the Google results page as JSON, $1.20 per 1,000 successful results, from $0.80.
- All scraper APIs
Google Flights Scraper FAQ
24/7 support by live chat, including help with setup and integration.
Is there a Google Flights scraper API?
ProxyField has no separate Google Flights API, but its Web Scraping API is designed to fetch Google Flights search pages with JS rendering for $2.00 per 1,000 successful results, or $1.00 from 10,000 results; access is through Contact sales. You send the search URL and get the rendered page back, and an evaluate step or your parser reads the fares.
Since Google Flights has no public API, how can I collect daily fares for a list of routes?
Fix one search per route (market, currency, passengers, cabin), send each search URL once a day with JS rendering, read the flight rows from the rendered page and append one row per route to a CSV with the time of the check, keeping the raw page so you can re-parse it. On ProxyField's Web Scraping API that is $2.00 per 1,000 successful results: one route daily for a year is $0.73, 50 routes daily are 1,500 pages a month, $3, and 100 routes are $6. For a few routes, Google's own "Track prices" emails you when a fare changes.
What is a Google Flights scraper?
A tool or script that collects what Google Flights shows for a route and a date: airlines, times, stops, duration, fares, price insights and the sellers behind each fare. It usually runs on a schedule, so you can see how fares move.
How do I scrape Google Flights?
Build the search URL for the route, date and passengers with the language, country and currency fixed, load it in a headless browser or with JS rendering, wait for the flight rows and read each flight's airline, stops and fare from them. Send the search from the market whose fares you want and repeat it on a schedule.
What data can I scrape from Google Flights?
Flight results with airline, times, duration, stops, layovers and fare, the price insight for the route, the date grid and price graph, booking options by airline and agency, and flight details such as aircraft and an emissions estimate. Tracked prices and saved trips need a Google account and are out of scope.
How do I scrape Google Flights with Python?
Use Playwright, because Google Flights builds its results with scripts: open the search URL through a proxy, wait for the flight rows and read their labels, as in the code on this page. Requests and Beautiful Soup alone get a page without the flights.
How do I handle JavaScript when scraping Google Flights?
Let a headless browser or JS rendering run the page and wait for a flight-row selector before you read it. Click "more flights" or the date grid only when you need them, because each extra step adds time and traffic.
Do I need an account to scrape Google Flights?
No: searches, results, price insights and booking options are visible without signing in, and a scraper should never sign in. Price tracking alerts and saved trips need a Google account and are out of scope.
How do I start scraping Google Flights?
Pick 5 routes, open their searches in a browser through a proxy in your target country, and note which fields you need. Then automate the same searches with Playwright or send the URLs to a scraping API, and add routes once the first ones parse cleanly.
Will I get blocked when scraping Google Flights?
You can be: many searches from one IP, datacenter ranges and clients that do not run the page's scripts get an "unusual traffic" page, a challenge or empty results. A headless browser on rotating residential IPs at a modest pace is blocked less often, and with ProxyField's Web Scraping API you pay only for successful results.
Show 7 more questionsShow fewer questions
Why does my Google Flights scraper break?
Usually Google changed the page, so your selectors find nothing, or your IP is throttled and gets a challenge instead of results. Save every page you receive: update the parser and re-parse if it has flights, slow down and rotate IPs if it does not.
How do I scrape Google Flights prices every day?
Schedule the same searches at the same time each day with cron, with the same country, currency and passengers, and store each fare with the route, dates and time of the check. Start with the date grid, which shows many days on one page, and fetch single dates only where you need detail.
Can I scrape Google Flights without writing code?
For a few routes, Google's own price tracking with a Google account sends you alerts, and a browser extension can export the visible results. For many routes on a schedule, you need a script or an API.
Does Google Flights have an API?
No: Google closed its QPX Express flight search API in 2018 and offers no public flight search API today. Airlines and some agencies have partner APIs for their own fares, so research across sellers means reading the Google Flights pages.
How much does it cost to scrape Google Flights?
On ProxyField's Web Scraping API, one route checked daily costs $0.73 a year, and a daily date-grid check on 100 routes is 3,000 pages a month: $6 at $2.00 per 1,000. Checking 50 routes on 60 departure dates every day is 90,000 pages: $180, or $90 at the volume price, which applies from 10,000 results in one purchase.
Can I scrape Google Flights fares for another country or currency?
Yes: set gl and curr in the URL and send the search through an IP in that country, because the point of sale changes which fares appear and at what price. ProxyField residential proxies offer targeting by country, region (state) and city, with 412M+ residential IPs in 195+ countries.
Why do teams scrape Google Flights?
Google Flights shows fares from many airlines and agencies on one page, with price insights and date grids, so it is a quick way to track fares by route, date and market. Airlines, travel startups and corporate travel teams use it for price history, deal alerts and budgets.
Related pages
Collect Google Flights pages with the Web Scraping API
Billed on successful results only. Contact sales for the Web Scraping API and the volume you need, or run your own scraper on residential proxies. 24/7 live chat helps with setup and integration.