farepy
Multi-source flight search with normalized results, caching, and batch support.
Query Google Flights, Ryanair, and more from a single Python function. Results are normalized into a common format so you can compare prices across sources without worrying about each API's quirks.
Install
pip install farepy[google_flights] # Google Flights (recommended, broadest coverage)
pip install farepy[ryanair] # Ryanair direct fares
pip install farepy[all] # Everything
Usage
Search flights
from farepy import search_flights
# One-way, all available sources
result = search_flights("MRS-REK", "2026-07-01")
for offer in result["offers"][:5]:
seg = offer["outbound"]["segments"][0]
print(
f"{offer['price']} {offer['currency']} {offer['airlines']} {seg['departure_time'][:16]}"
)
Pick a source
# Google Flights only (covers virtually all European LCCs)
result = search_flights("DUB-STN", "2026-07-01", sources=["google_flights"])
# Ryanair direct API (accurate fare-only pricing, includes flight numbers)
result = search_flights("DUB-STN", "2026-07-01", sources=["ryanair"])
# Both in parallel
result = search_flights("DUB-STN", "2026-07-01", sources=["google_flights", "ryanair"])
Round-trip
result = search_flights("DUB-STN", "2026-07-01", return_date="2026-07-08")
for offer in result["offers"][:3]:
out = offer["outbound"]["segments"][0]
ret = offer["inbound"]["segments"][0] if offer["inbound"] else None
print(
f"{offer['price']} {offer['currency']} out={out['departure_time'][:16]}",
end="",
)
if ret:
print(f" ret={ret['departure_time'][:16]}", end="")
print()
Filters
result = search_flights(
"MRS-REK",
"2026-07-01",
currency="USD",
adults=2,
non_stop=True,
outbound_departure_after="06:00",
outbound_departure_before="14:00",
)
Batch search
Search multiple routes and dates in one call. Combinations run sequentially to respect API rate limits; caching avoids re-querying repeated combinations.
from farepy import batch_search
results = batch_search(
legs=["MRS-REK", "CDG-KEF"],
departure_dates=["2026-07-01", "2026-07-02"],
return_dates=["2026-07-08"],
)
# Returns one SearchResult dict per combination (4 in this case)
Or from a text file:
from farepy import batch_from_file
results = batch_from_file("""
# route depart return
MRS-REK 2026-07-01 2026-07-08
CDG-KEF 2026-07-15 2026-07-22
DUB-STN 2026-08-01
""")
Cache
Results are cached locally for 24 hours by default (in ~/.local/share/farepy/cache/).
from farepy import list_cached_searches, get_cached_result, clear_cache
# See what's cached
for entry in list_cached_searches():
print(
f"{entry['origin']}-{entry['destination']} {entry['departure_date']} ({entry['num_offers']} offers)"
)
# Retrieve a cached result
result = get_cached_result(entry["cache_id"])
# Clear everything
clear_cache()
Disable caching per-search with use_cache=False, or adjust the TTL:
result = search_flights("MRS-REK", "2026-07-01", use_cache=False)
result = search_flights("MRS-REK", "2026-07-01", cache_ttl_hours=1)
Check available sources
from farepy import available_sources
for s in available_sources():
status = "ready" if s["available"] else "not installed"
print(f" {s['name']}: {status}")
Sources
| Source | Coverage | Install | Notes |
|---|---|---|---|
google_flights |
~All airlines via Google Flights | pip install farepy[google_flights] |
Protobuf API, no browser needed, broadest coverage |
ryanair |
Ryanair only | pip install farepy[ryanair] |
Direct fare finder API, includes flight numbers |
kayak |
~All airlines via Kayak | pip install farepy[kayak] |
Experimental, requires Playwright + Chromium |
Data model
Every source returns results normalized into the same structure:
SearchResult
request: SearchRequest # what was searched
offers: [FlightOffer] # sorted by price
sources_queried: [str] # which sources responded
sources_failed: {str: str} # source -> error message
searched_at: str # ISO 8601 timestamp
FlightOffer
source: str # "google_flights" | "ryanair" | "kayak"
outbound: Itinerary
inbound: Itinerary | None # None for one-way
price: float
currency: str
airlines: [str]
Itinerary
segments: [Segment]
duration_minutes: int | None
Segment
departure_airport: str # IATA code
arrival_airport: str # IATA code
departure_time: str # ISO 8601
arrival_time: str # ISO 8601 (empty if unavailable)
carrier: str
carrier_name: str | None
flight_number: str | None
duration_minutes: int | None
Results are returned as plain dicts (via dataclasses.asdict), so they serialize
to JSON directly.
Metadata
Release files for farepy 0.1.10
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| farepy-0.1.10.tar.gz | 32.7 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| farepy-0.1.10-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.7 kB
Release files / farepy-0.1.10.tar.gz
| Download URL | farepy-0.1.10.tar.gz |
|---|---|
| Size | 32.7 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
3795d3f14e0ddcd7e6b9752d1582abff5397618bfe605a4699db1d0650c988b3
|
|
BLAKE2b-256 checksum How to use checksums |
fbde7f06156084bd61d7d230f12b99d57f7c7679843af22be64c104877dde3b0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / farepy-0.1.10-py3-none-any.whl
| Download URL | farepy-0.1.10-py3-none-any.whl |
|---|---|
| Size | 39.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2a26dad289b822a489b79008777ac19cd1231fbacded6eb964984ae0760732e3
|
|
BLAKE2b-256 checksum How to use checksums |
472e8db31e04d8e92e85c6c89a962240ec7c40c0c9631455055b006702a30140
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|