Sign inTry it

Find Trenitalia trains and prices between two Italian stations.

Searches Trenitalia's own booking site (lefrecce.it) like its search form: departures from a given time between two stations or cities, with arrival, duration, changes, trains (Frecciarossa, Intercity, Regionale and numbers), the lowest available price in euros and whether it can still be bought. Filters: Frecce only, regional only, direct trains only, passengers.

No reports yetRead-only, no login
Site
Trenitalia (Le Frecce), Italy
Version
v2 of 2
Runs, last 7 days
No reports yet
sha256
2e5587c6293f…

Run it with your agent

after installing Wield

Ask in plain words. Your agent finds this recipe and calls it:

“Find Trenitalia trains and prices between two Italian stations.”

Read-only: it changes nothing on the site. No login needed.

{
  "tool": "run",
  "arguments": {
    "recipe_id": "lefrecce.it/search-trains",
    "params": {
      "departure": "2027-01-14T08:00",
      "from": "Roma",
      "to": "Milano"
    }
  }
}

Requests

sent from your browser, in order
  1. 1GET/Channels.Website.BFF.WEB/website/locations/search?limit&nameTrenitalia's station lookup (the search form calls it); the first match is used. Roma gives Roma (Tutte le stazioni), all of Rome's stations.
  2. 2GET/Channels.Website.BFF.WEB/website/locations/search?limit&nameTrenitalia's station lookup (the search form calls it); the first match is used. Roma gives Roma (Tutte le stazioni), all of Rome's stations.
  3. 3POST/Channels.Website.BFF.WEB/website/ticket/solutionsThe solutions search the booking site calls: a read-only POST (search API; nothing is reserved or added to a cart). Prices are the lowest fare still for sale per train.json body

Parameters

from your agent
adultsinteger = 1
childreninteger = 0
departurestringrequiredEarliest departure, Italian local time, e.g. '2027-01-14T08:00'
direct_onlybooleanNo changes = false
frecce_onlybooleanOnly high-speed Frecce trains = false
fromstringrequiredStation or city, e.g. 'Roma', 'Milano Centrale', 'Firenze S. M. Novella'
limitinteger = 10
regional_onlyboolean = false
tostringrequiredStation or city

Returns

to your agent
book_atstring
fromstring
tostring
trainsobject[]arrival, changes, departure, destination, duration, for_sale, origin, price_eur, price_indicative, trains, types

Where it can send

  • www.lefrecce.it

Anything else is blocked by the extension.

Reads from your session

Nothing. Your browser attaches the site's cookies by itself.

Used only in requests to the addresses on the left. Never sent to wield.run or your agent.

Checks

a run passes when
  • length(output.trains) > `3`
  • starts_with(output.trains[0].departure, '2027-01-14T')
  • length(output.trains[?price_eur > `0`]) > `0`
  • length(output.trains[?contains(types, 'FR')]) > `0`
  • output.from != `null` && output.to != `null`

Raw recipe

Served as canonical JSON from /api/v1/recipes/lefrecce.it/search-trains, so its sha256 matches the ETag and the index.

Check it yourself
curl -s https://wield.run/api/v1/recipes/lefrecce.it/search-trains | shasum -a 256
# 2e5587c6293feac8986e65dccbf53c787f9ba2e6ad1ab6cb91f95cc22c2dabc1
lefrecce.it/search-trains.json, v2
{
  "description": "Searches Trenitalia's own booking site (lefrecce.it) like its search form: departures from a given time between two stations or cities, with arrival, duration, changes, trains (Frecciarossa, Intercity, Regionale and numbers), the lowest available price in euros and whether it can still be bought. Filters: Frecce only, regional only, direct trains only, passengers.",
  "effect": "read",
  "id": "lefrecce.it/search-trains",
  "keywords": [
    "trenitalia",
    "treni",
    "orari",
    "biglietti",
    "frecciarossa",
    "frecciargento",
    "intercity",
    "regionale",
    "le frecce",
    "train",
    "italy",
    "rail",
    "timetable",
    "tickets"
  ],
  "output": {
    "schema": {
      "properties": {
        "book_at": {
          "type": "string"
        },
        "from": {
          "type": "string"
        },
        "to": {
          "type": "string"
        },
        "trains": {
          "items": {
            "properties": {
              "arrival": {
                "type": "string"
              },
              "changes": {
                "type": "integer"
              },
              "departure": {
                "description": "ISO time with offset",
                "type": "string"
              },
              "destination": {
                "type": "string"
              },
              "duration": {
                "description": "e.g. '3h 40min'",
                "type": [
                  "string",
                  "null"
                ]
              },
              "for_sale": {
                "type": "boolean"
              },
              "origin": {
                "type": "string"
              },
              "price_eur": {
                "description": "Lowest fare still for sale, for all passengers",
                "type": [
                  "number",
                  "null"
                ]
              },
              "price_indicative": {
                "type": "boolean"
              },
              "trains": {
                "description": "e.g. 'Frecciarossa 9516'",
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              "types": {
                "description": "Acronyms: FR (Frecciarossa), FA, FB, IC, REG, …",
                "items": {
                  "type": "string"
                },
                "type": "array"
              }
            },
            "type": "object"
          },
          "type": "array"
        }
      },
      "required": [
        "from",
        "to",
        "trains"
      ],
      "type": "object"
    },
    "value": "{from: steps.from.name, to: steps.to.name, trains: map(&{departure: departureTime, arrival: arrivalTime, duration: duration || `null`, origin: origin, destination: destination, changes: length(nodes || `[]`) - `1`, trains: map(&join(' ', [trainCategory || denomination || '', name || description || '']), trains || `[]`), types: map(&(acronym || ''), trains || `[]`), price_eur: price.amount || `null`, price_indicative: price.indicative == `true`, for_sale: status == 'SALEABLE'}, steps.solutions.solutions || `[]`), book_at: 'https://www.lefrecce.it/Channels.Website.WEB/'}"
  },
  "params": {
    "additionalProperties": false,
    "properties": {
      "adults": {
        "default": 1,
        "maximum": 9,
        "minimum": 1,
        "type": "integer"
      },
      "children": {
        "default": 0,
        "maximum": 9,
        "minimum": 0,
        "type": "integer"
      },
      "departure": {
        "description": "Earliest departure, Italian local time, e.g. '2027-01-14T08:00'",
        "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}$",
        "type": "string"
      },
      "direct_only": {
        "default": false,
        "description": "No changes",
        "type": "boolean"
      },
      "frecce_only": {
        "default": false,
        "description": "Only high-speed Frecce trains",
        "type": "boolean"
      },
      "from": {
        "description": "Station or city, e.g. 'Roma', 'Milano Centrale', 'Firenze S. M. Novella'",
        "maxLength": 60,
        "minLength": 2,
        "type": "string"
      },
      "limit": {
        "default": 10,
        "maximum": 10,
        "minimum": 1,
        "type": "integer"
      },
      "regional_only": {
        "default": false,
        "type": "boolean"
      },
      "to": {
        "description": "Station or city",
        "maxLength": 60,
        "minLength": 2,
        "type": "string"
      }
    },
    "required": [
      "from",
      "to",
      "departure"
    ],
    "type": "object"
  },
  "provenance": {
    "method": "browser-inspect",
    "notes": "lefrecce.it is Trenitalia's own sales site. Its search form calls GET /Channels.Website.BFF.WEB/website/locations/search?name=…&limit=5 for stations (multistation entries such as 'Roma ( Tutte Le Stazioni )' cover a whole city) and POST /Channels.Website.BFF.WEB/website/ticket/solutions with departureLocationId, arrivalLocationId, departureTime (local, ms precision), adults, children, criteria (frecceOnly, regionalOnly, noChanges, order, offset, limit) and advancedSearchRequest. The POST only searches; nothing is held or added to a cart (the response carries an empty cartId). Answers servers. verify.example_params uses a fixed date: move it forward before it passes. v2 (2026-11-07 22:38): read_only_post on 1 step only; requests and output unchanged.",
    "recorded_at": "2026-11-07T21:59:00+01:00",
    "recorded_by": "C4"
  },
  "requires_login": false,
  "schema": "https://wield.run/schema/recipe/v1.json",
  "site": {
    "country": "IT",
    "id": "lefrecce.it",
    "language": "it",
    "name": "Trenitalia (Le Frecce)",
    "origin": "https://www.lefrecce.it",
    "origins": [
      "https://www.lefrecce.it"
    ]
  },
  "steps": [
    {
      "description": "Trenitalia's station lookup (the search form calls it); the first match is used. Roma gives Roma (Tutte le stazioni), all of Rome's stations.",
      "expect": {
        "assert": "length(body) > `0`",
        "content_type": "json",
        "status": [
          200
        ]
      },
      "extract": {
        "json": {
          "id": "[0].id",
          "name": "[0].name"
        }
      },
      "id": "from",
      "request": {
        "headers": {
          "Accept": "application/json"
        },
        "method": "GET",
        "query": {
          "limit": "5",
          "name": "{{params.from}}"
        },
        "url": "/Channels.Website.BFF.WEB/website/locations/search"
      }
    },
    {
      "description": "Trenitalia's station lookup (the search form calls it); the first match is used. Roma gives Roma (Tutte le stazioni), all of Rome's stations.",
      "expect": {
        "assert": "length(body) > `0`",
        "content_type": "json",
        "status": [
          200
        ]
      },
      "extract": {
        "json": {
          "id": "[0].id",
          "name": "[0].name"
        }
      },
      "id": "to",
      "request": {
        "headers": {
          "Accept": "application/json"
        },
        "method": "GET",
        "query": {
          "limit": "5",
          "name": "{{params.to}}"
        },
        "url": "/Channels.Website.BFF.WEB/website/locations/search"
      }
    },
    {
      "description": "The solutions search the booking site calls: a read-only POST (search API; nothing is reserved or added to a cart). Prices are the lowest fare still for sale per train.",
      "expect": {
        "assert": "body.solutions != `null`",
        "content_type": "json",
        "status": [
          200
        ]
      },
      "extract": {
        "json": {
          "solutions": "solutions[].solution"
        }
      },
      "id": "solutions",
      "read_only_post": true,
      "request": {
        "body": {
          "type": "json",
          "value": {
            "adults": "{{params.adults}}",
            "advancedSearchRequest": {
              "bestFare": false,
              "bikeFilter": false
            },
            "arrivalLocationId": "{{steps.to.id}}",
            "children": "{{params.children}}",
            "criteria": {
              "frecceOnly": "{{params.frecce_only}}",
              "intercityOnly": false,
              "limit": "{{params.limit}}",
              "noChanges": "{{params.direct_only}}",
              "offset": 0,
              "order": "DEPARTURE_DATE",
              "regionalOnly": "{{params.regional_only}}",
              "tourismOnly": false
            },
            "departureLocationId": "{{steps.from.id}}",
            "departureTime": "{{params.departure}}:00.000"
          }
        },
        "headers": {
          "Accept": "application/json",
          "Content-Type": "application/json"
        },
        "method": "POST",
        "url": "/Channels.Website.BFF.WEB/website/ticket/solutions"
      }
    }
  ],
  "task": "Find Trenitalia trains and prices between two Italian stations",
  "tos": {
    "notes": "robots.txt only bans a few named crawlers. One station lookup per end and one search per call, the same requests the booking site's form makes; no booking, no cart.",
    "reviewed": false
  },
  "verify": {
    "checks": [
      "length(output.trains) > `3`",
      "starts_with(output.trains[0].departure, '2027-01-14T')",
      "length(output.trains[?price_eur > `0`]) > `0`",
      "length(output.trains[?contains(types, 'FR')]) > `0`",
      "output.from != `null` && output.to != `null`"
    ],
    "example_params": {
      "departure": "2027-01-14T08:00",
      "from": "Roma",
      "to": "Milano"
    },
    "max_ms": 6000
  },
  "version": 2
}