Site scraper

Google Flights Scraper: Daily Fares for a List of Routes

HTTP $0.50JS rendering $2.00 per 1,000 results or your own scraper from $1.95/GB

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.

Web Scraping API per 1,000 successful results
Web Scraping API prices per 1,000 successful results
FetchEntryVolume, from
HTTP$0.50$0.20
JS rendering$2.00$1.00

Billed on successful results only.

Your own scraper on residential proxies
from $1.95/GB Easy Trial: 1 GB for $2.95
gate.proxyfield.io:7000
Data

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 needUseWhat you getCost
Alerts on a few routesGoogle Flights' own "Track prices", signed in to a Google account (Google's help page)An email when a tracked fare changes; no table of pricesNothing
One airline's or a booking system's faresAirline and travel-industry APIs such as Amadeus, Sabre or Duffel, with partner accessThe seller's own fares, not what Google Flights showsSet by each program
Parsed Google Flights JSONA scraper-API vendor's Google Flights endpointFields as JSON, priced per search by the vendorSet by each vendor
A daily table for many routes, as travelers in one market see themThe ProxyField Web Scraping API (access through Contact sales), or your own browser on residential proxiesThe 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:

  1. Fix one search per route market (gl and 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.

  2. Once a day, send each route's search URL with JS rendering and wait for the flight rows.

  3. Read each row's label with an evaluate step and keep the lowest fare, with its airline and stops.

  4. 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.

  5. If a row shows 0 flights read, fix ROW or LABEL and re-parse that day's saved pages with reparse.py below, 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.

Python
# 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):

Shell
0 6 * * * cd /opt/fares && /usr/bin/python3 daily_fares.py

What 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.html

Step 5, re-parse a day's saved pages without new requests (python3 reparse.py 2026-12-01):

Python
# 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 read at 0 means the label did not match: open that day's saved page, adjust ROW or LABEL, 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.

Shell
# 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):

JSON
{
  "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": []
}
ChoicePrice per 1,000 successful resultsUse it for
JS rendering$2.00, $1.00 from 10,000 results in one purchaseFlight results, date grids, price graphs and booking options
Plain HTTP$0.50, $0.20 from 10,000 results in one purchaseAirline and agency pages you follow from the booking options, where they need no scripts
Pricing

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
Workload, Results, JS rendering at $2.00, JS rendering at $1.00 (from 10,000 results in one purchase)
WorkloadResultsJS rendering at $2.00JS rendering at $1.00 (from 10,000 results in one purchase)
1 route, daily, for a year365$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
Good to know

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 pageWhat it shows
Flight resultsAirline, departure and arrival times, duration, stops and layover airports, fare, the "best" flights first
Price insightsWhether today's fares are low, typical or high for the route, and a price history where shown
Date grid and price graphThe lowest fare for each departure and return date around your dates
Booking optionsWhich airlines and agencies sell the chosen flight, and at what price
Flight detailsAircraft, legroom and amenities where shown, and an emissions estimate
Explore mapDestinations 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.

Good to know

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.

Do it yourself

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.

Python
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.

Use cases

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.

FAQ

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.

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.