Why Travel Confirmations Are Harder to Read Than They Look
A booking confirmation looks like structured data. It has a flight number, a date, a time, a seat. Feeding it to a computer ought to be easy, and every few months someone builds a weekend project on that assumption and hits the same wall.
Here are the problems that actually bite, and what Petrel does about them.
There is no such thing as a standard confirmation
Every airline, hotel chain, rail operator, and tour desk formats its own. Some send clean HTML. Some send a PDF that is really a scanned image. Some send a wall of text with the flight buried in the middle. Aggregators reformat everything again, so the same flight looks different depending on where you booked it.
The naive approach is a template per provider, matching on known layouts. That works for the ten biggest airlines and falls over on the eleventh, and travel has a very long tail. Petrel does not keep per-provider templates. Everything goes through one extractor with a strict output schema, so a Japanese rail booking and an Airbnb receipt come out the same shape.
The year problem, which is worse than it sounds
Confirmations very often print a date with no year on it. "March 3." "3/3." "Fri 3 Mar." A human reading it in January knows exactly what that means. A parser has to emit a full date anyway, so it guesses, and it guesses wrong in two specific ways.
The first is booking ahead. You book in November for a trip in March, the confirmation says "March 3," and the parser stamps it with the current year. Your trip is now in the past.
The second is nastier. A trip that crosses New Year, say 30 December to 2 January, gets every date stamped with the same year, so the January half of your holiday lands eleven months before the December half. The itinerary is not just wrong, it is unreadable.
Petrel runs a separate pass after the extraction to fix this, and it is deliberately not another model call. It is a plain function with no clock and no network, which means it can be tested exhaustively. It works in priority order: if the trip's own date range is known, pick the year that puts the date inside it, which is what repairs the New Year wrap. Failing that, anchor to today and choose the next occurrence, because a booking with no year is nearly always upcoming. If neither applies, leave the date alone rather than invent one.
That last rule matters. A parser that guesses confidently is worse than one that admits it does not know.
The same flight, arriving twice
You forward the airline's confirmation. Later you upload a calendar export that contains the same flight. Both are legitimate, and a naive importer now shows your flight twice.
The obvious fix is to match on the confirmation code, and it is wrong. A package booking prints one reference across every component, so matching on the code alone merges your flight with your hotel. Identity has to agree on more than the reference: the route and the date have to line up too.
Why this is the interesting part
Extracting text from a document is close to solved. What is left is the judgement around it: knowing which year a bare date belongs to, knowing when two records are the same real-world thing, and knowing when to leave a field empty instead of filling it with a confident guess.
None of that is glamorous, and all of it is the difference between an itinerary you trust and one you check by hand, which defeats the point.
You can see the result without signing up. Forward a confirmation or upload a PDF, and your first trip is free with no account and no card.
Try it on your next trip
Forward a confirmation email, a screenshot, or a PDF and watch Petrel build your day-by-day itinerary.
Plan your first trip freeFirst trip free. No account, no credit card.