directferries APIdirectferries.it ↗
Search Italian ferry ports, routes, and live sailing prices from directferries.it. Two endpoints cover port lookup and one-way sailing search with passengers and vehicle.
What is the directferries API?
The directferries.it API exposes two endpoints for querying Mediterranean and Italian ferry data: search_locations resolves free-text port names to structured port codes and popular routes, while search_ferries returns live-quoted sailings between two ports on a given date, including per-sailing departure times, operator, duration, price per person, and total cost broken down by passenger type and vehicle.
curl -X GET 'https://api.parse.bot/scraper/951632b3-d49f-446e-ab88-2842f27d1dcb/search_locations?query=napoli' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace directferries-it-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Direct Ferries (IT) — find ports, search sailings, read prices."""
from parse_apis.directferries_it_api import DirectFerries, Currency, InputNotFound
client = DirectFerries()
# Find ports matching a city name and grab the first available route.
route = client.routes.search(query="napoli", limit=5).first()
if route is None:
raise SystemExit("no routes found for query")
print(f"Route: {route.origin_name} → {route.destination_name}")
# Use the discovered port codes to search sailings on a specific date.
try:
result = client.ferry_searches.search(
origin_id=route.origin_id,
destination_id=route.destination_id,
departure_date="2026-10-26",
adults=2,
currency=Currency.EUR,
)
except InputNotFound:
raise SystemExit("unknown port code — check route IDs")
print(f"Search complete: {result.search_complete}, currency: {result.currency}")
# Browse sailings and print key details.
if result.sailings:
for sailing in result.sailings[:5]:
print(
f" {sailing.operator} | {sailing.departure_datetime} → {sailing.arrival_datetime}"
f" | {sailing.duration_minutes}min | €{sailing.total_price}"
)
if sailing.stops:
for stop in sailing.stops:
print(f" stop: {stop.name}")
# Also list matching port locations for reference.
for loc in client.locations.search(query="napoli", limit=3):
print(f"Port: {loc.name} ({loc.id}), {loc.country}")
print("exercised: routes.search / ferry_searches.search / locations.search")
Finds ferry ports matching a free-text name (Italian names are accepted, e.g. one shape: 'napoli') and lists popular routes for the match. With origin_id instead of (or in addition to) a text query, it returns the ports reachable from that origin and the routes involving it. Each location carries the port code that search_ferries takes as origin_id / destination_id. One round trip, no pagination; an unmatched name yields empty lists.
| Param | Type | Description |
|---|---|---|
| query | string | Free-text port, island or region name to match. Either query or origin_id must be supplied. |
| origin_id | string | Port code (from search_locations.locations[*].id) to restrict results to destinations reachable from that port. When given without query, lists that port's destinations. |
{
"type": "object",
"fields": {
"query": "the text that was matched",
"routes": "array of popular routes related to the match: origin_id, origin_name, origin_country, destination_id, destination_name, destination_country",
"locations": "array of matching ports: id (port code used by search_ferries), name, country, country_code, region, area (null when the site gives none)"
},
"sample": {
"data": {
"query": "napoli",
"routes": [
{
"origin_id": "NAP",
"origin_name": "Napoli",
"destination_id": "ITPRJ",
"origin_country": "Italia",
"destination_name": "Capri",
"destination_country": "Italia"
},
{
"origin_id": "NAP",
"origin_name": "Napoli",
"destination_id": "PLE",
"origin_country": "Italia",
"destination_name": "Palermo",
"destination_country": "Italia"
}
],
"locations": [
{
"id": "NAP",
"area": null,
"name": "Napoli",
"region": null,
"country": "Italia",
"country_code": "IT"
}
]
},
"status": "success"
}
}About the directferries API
Port and Route Discovery
The search_locations endpoint accepts a free-text query (Italian names like napoli are supported) and returns two arrays. locations contains matching ports with fields id (the port code used throughout the API), name, country, country_code, region, and area. routes contains popular route pairings related to the match, each with origin_id, origin_name, origin_country, destination_id, and destination_name. Passing an origin_id instead of (or alongside) a text query narrows results to destinations reachable from that specific port, making it straightforward to build a two-step origin → destination selection flow.
Live Sailing Search
search_ferries takes a required origin_id, destination_id, and ISO departure_date, plus optional passenger counts (adults, children, infants), pets, vehicle_type, and currency. It returns a sailings array where each record includes trip_id, route_type, origin_id, origin_name, destination_id, destination_name, departure_datetime, arrival_datetime (both in local port time), operator, vessel, sailing duration, price per person, and total price. The response-level currency field reflects whichever ISO currency was requested.
Freshness and Completeness
The search_complete boolean in the search_ferries response signals whether all operator quotes were collected before the response was returned. A false value means the site had not finished aggregating quotes within the wait window, so the sailings array may be a partial result for that route and date. Callers should inspect this flag before treating the result as exhaustive. Pricing reflects the live quoted fare at query time and may change between requests.
The directferries API is a managed, monitored endpoint for directferries.it — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when directferries.it changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official directferries.it API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Display available sailings and live fares for a Naples–Palermo route on a specific date
- Build a port autocomplete widget backed by Italian-language port name matching
- Compare sailing durations and operator prices for a given island route
- Filter sailings by vehicle type to quote car-ferry fares versus foot-passenger fares
- List all ports reachable from a given origin to populate a destination dropdown
- Track fare changes over time for a fixed route by polling search_ferries daily
- Surface popular route pairings for a region to guide users toward common connections
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.
Does directferries.it have an official developer API?+
What does search_locations return when I pass an origin_id without a text query?+
locations array still carries the same fields (id, name, country, country_code, region, area), and routes lists origin–destination pairs filtered to that port's network.What does the search_complete flag mean, and when should I act on it?+
search_complete is false, the sailings array in the response is a partial list because not all operator quotes were received within the response window. If completeness matters for your use case, you may want to retry the request or treat the result as provisional.Does the API support round-trip or multi-leg ferry searches?+
search_ferries endpoint covers one-way sailings only. To model a round trip, you would make two separate calls with the origin and destination swapped. You can fork this API on Parse and revise it to add a dedicated round-trip endpoint if your application requires combined outbound and return results in a single call.