# TrailLink Trail Scraper (`maximedupre/traillink`) Actor

Find public TrailLink trails with one location or keyword, or read submitted trail-page URLs. Get structured trail names, lengths, surfaces, activities, locations, categories, descriptions, review counts, ratings, photo links, and source links when available.

- **URL**: https://apify.com/maximedupre/traillink.md
- **Developed by:** [Maxime Dupré](https://apify.com/maximedupre) (community)
- **Categories:** Travel, Sports, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$9.00 / 1,000 trails

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### 🌲 Build a TrailLink trail dataset

For hiking app researchers, outdoor data teams, and developers, this Actor turns public TrailLink pages into structured trail records. Get trail names, lengths, surfaces, activities, locations, and categories, plus descriptions, review counts, ratings, photo links, and source links when available.

- Find a TrailLink option with the **[AllTrails Free Alternative](https://apify.com/maximedupre/traillink/examples/alltrails-free-alternative)** example.
- Compare the two sources with the **[TrailLink vs AllTrails](https://apify.com/maximedupre/traillink/examples/traillink-vs-alltrails)** example.
- Find hiking-focused trail ideas with the **[Best Hiking Apps Free](https://apify.com/maximedupre/traillink/examples/best-hiking-apps-free)** example.
- Start a broad trail search with the **[Trail Apps](https://apify.com/maximedupre/traillink/examples/trail-apps)** example.
- Look for cycling-friendly trails with the **[Bike Trail App Free](https://apify.com/maximedupre/traillink/examples/bike-trail-app-free)** example.
- Search Rails-to-Trails pages with the **[Rails-to-Trails App](https://apify.com/maximedupre/traillink/examples/rails-to-trails-app)** example.

#### 🧭 Read TrailLink trail facts

Each saved row describes one eligible source trail. The Output section shows a complete row from the current beta run. Optional fields appear when TrailLink provides them.

#### ▶️ Run one focused TrailLink request

Choose **Location or keyword** to send one request with a place or search term. Choose **Trail page URLs** to read submitted public TrailLink pages. Only fields for the chosen method are used. The Actor reads public pages and does not need customer-provided TrailLink credentials. Use separate runs for separate location or keyword requests.

#### ⚙️ Input

**Input fields**

| Field | Type | What it does |
| --- | --- | --- |
| `discoveryMethod` | string | Required. Choose `search` for one location or keyword request, or `trailUrls` for submitted TrailLink trail pages. |
| `searchQuery` | string | One place or keyword to use in a search request. Use it with `discoveryMethod: "search"`. |
| `trailUrls` | array of objects | Public TrailLink page URLs to read. Use it with `discoveryMethod: "trailUrls"`. |
| `trailUrls[].url` | URL string | One public TrailLink trail-page URL. |

**Example input**

This is the smallest successful search input from the current beta runs.

```json
{
  "discoveryMethod": "search",
  "searchQuery": "cherry creek regional trail"
}
```

#### 🧾 Output

After a run, the `dataset` output link opens the returned trail rows.

| Field | Type | What it does |
| --- | --- | --- |
| `name` | string | Trail name from TrailLink. |
| `length` | string | Trail length, including its unit. |
| `surface` | string | Surface types listed for the trail. |
| `activities` | array of strings | Activities listed for the trail. |
| `location` | string | Trail location shown by TrailLink. |
| `category` | string | Trail category listed by TrailLink. |
| `description` | string | Human-readable trail description when available. |
| `reviewCount` | integer | Number of reviews when available. |
| `rating` | number | Trail rating from 0 to 5 when available. |
| `photoUrl` | URL string | Direct trail photo link when available. |
| `sourceUrl` | URL string | Public TrailLink page when available. |

**Example output row**

The row below is a complete, unshortened row from the current beta run.

```json
{
  "name": "Cherry Creek Regional Trail",
  "length": "47.8 miles",
  "surface": "Asphalt, Concrete, Gravel",
  "activities": [
    "Bike",
    "Inline Skating",
    "Walking",
    "Wheelchair Accessible"
  ],
  "location": "Aurora, CO, Colorado",
  "category": "Greenway/Non-RT",
  "description": "The Cherry Creek Regional Trail is a picturesque 47-mile route with a northern endpoint in downtown Denver and connects suburban and rural Arapahoe and Douglas Counties, including the communities of Parker, Centennial, and Franktown. The vast majority of the trail has an 8-foot-wide concrete surface, but short sections of the more rural southern end consist of gravel trails and roads. About the Route The trail's northern endpoint is located at Denver's Confluence Park, which marks the area where a gold discovery in 1858 led to the founding of the city. Meandering southeast, the trail parallels Cherry Creek through urban landscapes and parks and into the suburbs. Highlights of the route include the Cherry Creek Shopping District Four Mile House and Historic Park, where one can learn about Denver's early pioneers. In Arapahoe County, the trail emerges in Cherry Creek State Park, which offers several hiking trails, campgrounds, and a vast array of recreational opportunities around Cherry Creek Reservoir. Near the park's southern edge, the trail goes under Arapahoe Road (State Route 88), allowing trail users to seamlessly continue their southward journey uninterrupted by busy traffic. Just before entering Douglas County, trail-goers pass through the Parker Jordan Centennial Open Space. Purchased by the Parker Jordan Metropolitan District in 2009, the formerly private 107 acres with Cherry Creek snaking through it are now preserved in perpetuity. Continuing south over the county line, the trail passes through suburban and then increasingly rural areas. Connections At the trail's northern end, it connects to the Platte River Trail (CO). In the Hampden neighborhood of Denver, it connects to the Hampden Heights Trail and the High Line Canal Trail. In Centennial, the Piney Creek Trail and the Happy Canyon Trail lead off from the Cherry Creek Regional Trail. In Creekside, the trail connects to the Baldwin Gulch Trail, Newlin Gulch Trail, and Sulphur Gulch Trail. Parking and Trail Access The Cherry Creek Regional Trail runs between Platte River Trail at Confluence Park (Denver) and Homestead Canyon Rd., Castlewood Canyon Rd. (Franktown), where parking is available. Parking is also available at: 494 S Clermont St (Glendale) 2998 S Kenton St (Aurora) 17330 Cottonwood Dr (Parker) There are numerous parking options along the route, please see TrailLink Map for all parking options and detailed directions.",
  "reviewCount": 32,
  "rating": 5,
  "photoUrl": "https://cloudfront.traillink.com/photos/cherry-creek-regional-trail_61707_hero.jpg",
  "sourceUrl": "https://www.traillink.com/trail/cherry-creek-regional-trail/"
}
```

#### 💳 Pricing

The primary event is **Trail**. It is charged once for each successfully returned trail. The current event price is $0.009 per trail. Check the live pricing panel for the current price before a run.

#### 🔌 Integrations

Use Apify's run tools or API, then pass the dataset output to your workflow. This Actor reads public TrailLink pages and returns structured rows in the Apify dataset.

https://www.youtube.com/watch?v=bNACk1\_S\_6w\&list=PLObrtcm1Kw6MUrlLNDbK9QRg8VDJg0gOW\&index=4

#### ❓ FAQ

##### Can I search more than one location or keyword in one run?

No. Each search run uses one location or keyword request. Use a separate run for another request.

##### Can I submit TrailLink page URLs?

Yes. Choose Trail page URLs and add the public TrailLink pages you want to read.

##### What fields may be missing?

Descriptions, review counts, ratings, photo links, and source links are returned when available on the source page. Core fields are name, length, surface, activities, location, and category.

##### Are GPS coordinates included?

No. GPS coordinates are outside this Actor's committed trail data.

##### Can I filter by activity, surface, rating, or distance?

No. The input has no user-selected filters. Search by one location or keyword, or submit trail pages.

##### Do I need a TrailLink login?

No. The Actor reads public TrailLink pages without customer-provided source credentials.

##### What happens when the same trail matches more than once?

The first eligible occurrence is saved. Later matches for the same source trail are ignored.

### 📝 Changelog

**v0.0** (28-09-2026)

- Initial release.

### 🆘 Support

For issues, questions, or feature requests, [file a ticket](https://console.apify.com/actors/maximedupre~traillink/issues) and I'll fix or implement it in less than 24h 🫡

### 🔗 Related Actors

- **Strava Community Hub Scraper** ([Store page](https://apify.com/maximedupre/strava)): Search public Strava activities and community pages when you need activity context beside trail records.
- **TrailLink Trail Scraper** ([Store page](https://apify.com/lulzasaur/traillink-scraper)): Compare another TrailLink trail data source for a second collection path.
- **AllTrails Hiking Scraper - Trails, Stats & Reviews** ([Store page](https://apify.com/abotapi/alltrails-hiking-scraper)): Collect broader hiking trail stats and reviews from AllTrails.
- **WTA Washington Trails Scraper** ([Store page](https://apify.com/crawlerbros/wta-trails-scraper)): Collect Washington Trails Association records when your research is regional.
- **Hiking Project Scraper** ([Store page](https://apify.com/lulzasaur/hikingproject-scraper)): Search Hiking Project trails by location or trail name for a second trail source.

**Made with ❤️ by Maxime Dupré**

# Actor input Schema

## `discoveryMethod` (type: `string`):

Choose whether to search with one location or keyword or read submitted TrailLink trail pages.

## `searchQuery` (type: `string`):

Enter one place or keyword to find public TrailLink trails.

## `trailUrls` (type: `array`):

Add one or more public TrailLink trail-page URLs to read.

## Actor input object example

```json
{
  "discoveryMethod": "search",
  "searchQuery": "hiking trails in Denver"
}
```

# Actor output Schema

## `dataset` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "discoveryMethod": "search",
    "searchQuery": "hiking trails in Denver"
};

// Run the Actor and wait for it to finish
const run = await client.actor("maximedupre/traillink").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "discoveryMethod": "search",
    "searchQuery": "hiking trails in Denver",
}

# Run the Actor and wait for it to finish
run = client.actor("maximedupre/traillink").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "discoveryMethod": "search",
  "searchQuery": "hiking trails in Denver"
}' |
apify call maximedupre/traillink --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,maximedupre/traillink"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/aTQhgap9qAvWRCgGh/builds/hle7IdkVyamhNHV0a/openapi.json
