{"description":"Ryanair's fare finder for one route: for every day in a date range (up to two calendar months), the cheapest one-way fare for one adult with its departure and arrival time, in the currency you choose. Add a return range to get the way back too. Days without a flight or sold out are left out. Each flight links to Ryanair's flight selection for that day, where seats, bags and the final price are shown and booked.","effect":"read","id":"ryanair.com/search-flights","keywords":["ryanair","flights","cheap flights","low cost","fare finder","one way","return","flug","flüge","billigflug","günstig fliegen","vuelos baratos","voli low cost","lot","airline","airport","iata"],"output":{"schema":{"$defs":{"flight":{"properties":{"arrival":{"description":"Local time at the arrival airport","type":"string"},"currency":{"type":"string"},"date":{"description":"Departure day, YYYY-MM-DD","type":"string"},"departure":{"description":"Local time at the departure airport, YYYY-MM-DDTHH:MM:SS","type":"string"},"from":{"type":"string"},"price":{"description":"Cheapest fare that day for one adult, before bags and seats","type":"number"},"to":{"type":"string"},"url":{"description":"Ryanair's flight selection for that day","type":"string"}},"type":"object"}},"properties":{"cheapest_outbound":{"type":["object","null"]},"cheapest_return":{"type":["object","null"]},"currency":{"type":"string"},"destination":{"type":"string"},"origin":{"type":"string"},"outbound":{"items":{"$ref":"#/$defs/flight"},"type":"array"},"return":{"description":"Empty for one way","items":{"$ref":"#/$defs/flight"},"type":"array"}},"required":["origin","destination","currency","outbound","return"],"type":"object"},"value":"let $cur = params.currency || 'EUR', $max = params.max_price, $olo = to_number(join('', split(params.date_from, '-'))), $ohi = to_number(join('', split(params.date_to || params.date_from, '-'))), $rlo = params.return_from && to_number(join('', split(params.return_from, '-'))), $rhi = params.return_from && to_number(join('', split(params.return_to || params.return_from, '-'))) in let $all = map(&(let $c = @ in map(&(let $x = @ in {leg: $c.f.leg, n: to_number(join('', split($x.day, '-'))), date: $x.day, from: $c.f.from, to: $c.f.to, departure: $x.departureDate, arrival: $x.arrivalDate, price: $x.price.value, currency: $x.price.currencyCode || $cur, url: join('', ['https://www.ryanair.com/gb/en/trip/flights/select?adults=1&teens=0&children=0&infants=0&dateOut=', $x.day, '&isConnectedFlight=false&isReturn=false&discount=0&originIata=', $c.f.from, '&destinationIata=', $c.f.to])}), $c.fares[?price != `null` && !soldOut && !unavailable] || `[]`)), steps.fares || `[]`)[] in let $out = sort_by($all[?leg == 'outbound' && n >= $olo && n <= $ohi && ($max == `null` || price <= $max)], &n)[*].{date: date, from: from, to: to, departure: departure, arrival: arrival, price: price, currency: currency, url: url}, $ret = sort_by($all[?leg == 'return' && $rlo != `null` && n >= $rlo && n <= $rhi && ($max == `null` || price <= $max)], &n)[*].{date: date, from: from, to: to, departure: departure, arrival: arrival, price: price, currency: currency, url: url} in {origin: upper(params.origin), destination: upper(params.destination), currency: $cur, outbound: $out, return: $ret, cheapest_outbound: min_by($out, &price) || `null`, cheapest_return: min_by($ret, &price) || `null`}"},"params":{"additionalProperties":false,"properties":{"currency":{"default":"EUR","enum":["EUR","GBP","PLN","HUF","CZK","SEK","NOK","DKK","CHF","MAD","RON","BGN"],"type":"string"},"date_from":{"description":"First departure day, YYYY-MM-DD","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"},"date_to":{"description":"Last departure day, YYYY-MM-DD (default: date_from). Same or next calendar month as date_from","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"},"destination":{"description":"Arrival airport IATA code, e.g. 'BCN' (Barcelona), 'BGY' (Milan Bergamo)","pattern":"^[A-Za-z]{3}$","type":"string"},"max_price":{"description":"Leave out days whose cheapest fare is higher, in the chosen currency","minimum":0,"type":"number"},"origin":{"description":"Departure airport IATA code, e.g. 'BER' (Berlin), 'STN' (London Stansted), 'DUB' (Dublin)","pattern":"^[A-Za-z]{3}$","type":"string"},"return_from":{"description":"First day for the way back (destination → origin), YYYY-MM-DD. Leave out for one way","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"},"return_to":{"description":"Last day for the way back (default: return_from). Same or next calendar month as return_from","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},"required":["origin","destination","date_from"],"type":"object"},"provenance":{"method":"browser-inspect","notes":"Ryanair's fare finder pages call /api/farfnd/v4/oneWayFares/<from>/<to>/cheapestPerDay?outboundMonthOfDate=<YYYY-MM-01>&currency=<code>: one entry per day of that month with the cheapest one-way fare, departure and arrival (local times, no offset), soldOut and unavailable flags. currency converts (STN→DUB in EUR works). The booking availability API (/api/booking/v4/<market>/availability) answers servers and cookie-less clients with 409 'Availability declined', so this recipe uses the fare finder only: prices are for one adult before bags, seats and fees, and the link opens Ryanair's own flight selection. Dates are compared as numbers (JMESPath here compares numbers, not strings). Answers servers.","recorded_at":"2026-11-07T21:32:00+01:00","recorded_by":"C4"},"requires_login":false,"schema":"https://wield.run/schema/recipe/v1.json","site":{"country":"IE","id":"ryanair.com","language":"en","name":"Ryanair","origin":"https://www.ryanair.com","origins":["https://www.ryanair.com"]},"steps":[{"description":"The fare finder's cheapest-per-day API, once per leg and calendar month (at most 4 requests). The one-item-per-call list says which leg and month each call is for.","expect":{"assert":"body.outbound.fares != `null`","content_type":"json","status":[200]},"extract":{"json":{"fares":"outbound.fares"}},"foreach":{"as":"f","in":"let $o = upper(params.origin), $d = upper(params.destination), $to = params.date_to || params.date_from, $rf = params.return_from, $rt = params.return_to || params.return_from in [{leg: 'outbound', from: $o, to: $d, month: join('', [params.date_from[0:7], '-01'])}, {leg: 'outbound', from: $o, to: $d, month: ($to[0:7] != params.date_from[0:7]) && join('', [$to[0:7], '-01']) || `null`}, {leg: 'return', from: $d, to: $o, month: $rf && join('', [$rf[0:7], '-01']) || `null`}, {leg: 'return', from: $d, to: $o, month: ($rf && $rt[0:7] != $rf[0:7]) && join('', [$rt[0:7], '-01']) || `null`}][?month]","max":4},"id":"fares","request":{"headers":{"Accept":"application/json"},"method":"GET","query":{"currency":"{{params.currency}}","outboundMonthOfDate":"{{f.month}}"},"url":"/api/farfnd/v4/oneWayFares/{{f.from}}/{{f.to}}/cheapestPerDay"}}],"task":"Find the cheapest Ryanair flight on a route, day by day","tos":{"notes":"Ryanair's website terms allow private, non-commercial use and forbid automated extraction for commercial purposes (screen scraping). This recipe is for one person's own search: 1–4 requests, the same ones the fare finder makes. robots.txt disallows /api for crawlers. Booking stays on ryanair.com.","reviewed":false},"verify":{"checks":["length(output.outbound) > `2`","length(output.outbound) <= `7`","length(output.outbound[?starts_with(date, '2027-01-1')]) == length(output.outbound)","output.cheapest_outbound.price > `0`","length(output.outbound[?currency == 'EUR' && price > `0` && starts_with(url, 'https://www.ryanair.com/')]) == length(output.outbound)","length(output.return) == `0`"],"example_params":{"date_from":"2027-01-11","date_to":"2027-01-17","destination":"BCN","origin":"BER"},"max_ms":4000},"version":1}