# SkylineWebcams Live Webcams Scraper (`automation-lab/skyline-tourist-webcam-directory`) Actor

Export SkylineWebcams camera names, descriptions, country codes, page links, displayed host credits and short-lived HLS manifest observations for travel catalogue refreshes. No recording or permanent-stream guarantee.

- **URL**: https://apify.com/automation-lab/skyline-tourist-webcam-directory.md
- **Developed by:** [Automation Lab](https://apify.com/automation-lab) (community)
- **Categories:** Travel, Videos
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $4.80 / 1,000 camera catalogue records

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## SkylineWebcams Live Webcams Scraper

Refresh a travel-content catalogue of **skylinewebcams live webcams** by country. Export camera names, short descriptions, exact camera pages, displayed host credits and short-lived observed HLS manifest URLs when the public page exposes them.

The Actor returns one camera per dataset row and a country-grouped JSON file. It does not record video, download snapshots, verify playback, or guarantee permanent stream links. A missing or unavailable stream does not discard otherwise useful catalogue metadata.

### Who is this for?

- Travel-content teams refreshing destination camera catalogues.
- Developers maintaining country-indexed webcam discovery lists.
- Data teams comparing dated catalogue snapshots in their own storage.

### Why use this Actor?

Country codes, stable page links and observation timestamps make repeat exports easier to join. Displayed host credits remain attached to their camera instead of being lost during manual copying. A small manifest request distinguishes an observed HLS response from a URL that was merely present in HTML.

This is a catalogue product, not a licensed media feed or weather service. It collects only public SkylineWebcams pages, without customer credentials or paid proxy configuration.

### What data is extracted?

| Field | Meaning |
| --- | --- |
| `countryCode` | ISO 3166-1 alpha-2 code, for example IT |
| `countryName` | Normalized country name |
| `sourceCountryName` | Country/territory label displayed by the source |
| `cameraId` | Public player identifier, nullable |
| `name`, `description` | Displayed camera heading and short attraction description |
| `pageUrl` | Exact public English camera-detail page |
| `hostCredits` | Displayed host labels and source credit links; empty if absent |
| `streamUrl` | Observed short-lived HLS manifest URL, nullable |
| `streamStatus` | `manifest_available`, `manifest_unavailable`, or `not_exposed` |
| `streamObservedAt`, `scrapedAt` | ISO observation and extraction timestamps |
| `attributionNote` | Reminder that credits do not establish reuse permission |

`manifest_available` means the fetched response begins with `#EXTM3U`. It does not mean media segments played, that a camera is currently live, or that the URL will work from your network.

### How to get started

1. Open the Actor and select country codes, initially `IT`.
2. Set the global maximum records and per-country maximum.
3. Start the run.
4. Open the camera dataset or the country-grouped JSON link in Output.
5. Export JSON, CSV or Excel through Apify's dataset tools.

For country discovery:

```json
{"countries":["IT","MT"],"maxItems":20,"maxItemsPerCountry":10}
```

For exact camera pages, clear the country selection:

```json
{
  "countries":[],
  "startUrls":[{"url":"https://www.skylinewebcams.com/en/webcam/italia/lazio/roma/fontana-di-trevi.html"}],
  "maxItems":1,
  "maxItemsPerCountry":1
}
```

### Input parameters

| Input | Default | Behavior |
| --- | --- | --- |
| `countries` | `["IT"]` | Up to 10 supported uppercase ISO country codes, deduplicated in order |
| `startUrls` | `[]` | Up to 50 exact HTTPS English camera-detail pages; mutually exclusive with nonempty countries |
| `maxItems` | `10` | Global unique camera-row limit, 1–100 |
| `maxItemsPerCountry` | `10` | Country-row limit across either route, 1–20 |

The schema lists supported countries. This reflects the current public directory, not coverage of every country worldwide. `GB` is the United Kingdom code. The source's Zanzibar category maps to `TZ` (Tanzania); it does not cover all Tanzanian cameras. Country codes are ISO 3166-1 alpha-2, not subdivision codes from ISO 3166-2.

For `startUrls`, only `url` is consumed. Custom `method`, `headers`, `payload` and `userData` are ignored and not applied to requests, even if a hosted MCP client exposes those standard request-list options. Camera pages use the Actor's own GET requests.

Earlier countries can consume the global limit. Set a per-country cap for a more balanced collection. Limits are row counts, not counts of working streams. Duplicate URLs are removed; unavailable-stream records still count. No keyword, city, location search, scene filter or unlimited mode is implemented.

### Output example

A real camera-page result has this structure; the expiring URL token is omitted here:

```json
{
  "countryCode":"IT",
  "countryName":"Italy",
  "sourceCountryName":"Italy",
  "cameraId":"286",
  "name":"Trevi Fountain - Rome",
  "description":"View of the Trevi Fountain in Rome",
  "pageUrl":"https://www.skylinewebcams.com/en/webcam/italia/lazio/roma/fontana-di-trevi.html",
  "hostCredits":[{"name":"Webcam host","creditUrl":"https://www.skylinewebcams.com/click.php?l=..."}],
  "streamUrl":"https://hd-auth.skylinewebcams.com/live.m3u8?a=...",
  "streamStatus":"manifest_available",
  "streamObservedAt":"2026-10-03T14:00:00.000Z",
  "scrapedAt":"2026-10-03T14:00:00.000Z",
  "attributionNote":"Displayed host credits only; this record does not establish reuse permission or a complete legal attribution requirement."
}
```

Values and availability change. Some host images have only the generic label “Webcam host”; the Actor preserves that label rather than inventing a company name.

### Country-grouped JSON

The default key-value store's `COUNTRIES` record contains:

```json
[{"countryCode":"IT","countryName":"Italy","webcams":[{"name":"Trevi Fountain - Rome","pageUrl":"..."}]}]
```

Each webcam contains the full dataset fields; this shortened illustration shows the grouping only. The observation summary reports saved rows, country codes and manifest availability. Both JSON files are included in the camera-record price. If a later page fails, existing rows and the group file are partial; check run status before treating them as a complete export.

### How much does it cost to export SkylineWebcams camera catalogues?

Pay-per-event pricing charges a **$0.005 start fee per run**, plus each unique camera catalogue record saved. Unavailable-stream metadata records are also charged; failed pages and duplicates are not.

| Plan tier | Per camera record |
| --- | --- |
| FREE | $0.0092 |
| BRONZE | $0.008 |
| SILVER | $0.00624 |
| GOLD / PLATINUM / DIAMOND | $0.0048 |

BRONZE run totals including the start fee: 1 camera — $0.013; 10 cameras — $0.085; 100 cameras — $0.805. Your applicable plan tier determines the per-record price. Use Apify's maximum charge per run to control spending; a billing cap can stop collection before the requested row limit.

### Integrations and recurring refreshes

Save the input as an Apify Task and attach an Apify schedule for recurring exports. Join snapshots by `pageUrl` or `cameraId` in a spreadsheet, database or warehouse. Compare names, descriptions and credit links, not expiring stream tokens as permanent identifiers.

Connect completion webhooks to your ingestion pipeline, or use Apify integrations to send dataset rows to Google Sheets. Retain full JSON for nested host credits and country grouping. This Actor does not itself store historical changes, send change alerts or monitor cameras between runs.

### API examples

Use a managed Apify token; do not put credentials into Actor input.

```bash
curl -X POST "https://api.apify.com/v2/acts/automation-lab~skyline-tourist-webcam-directory/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" -H "Content-Type: application/json" \
  -d '{"countries":["IT"],"maxItems":10,"maxItemsPerCountry":10}'
```

JavaScript with `apify-client`:

```javascript
const client = new ApifyClient({token: process.env.APIFY_TOKEN});
const run = await client.actor('automation-lab/skyline-tourist-webcam-directory').call({countries:['IT'], maxItems:10});
const {items} = await client.dataset(run.defaultDatasetId).listItems({limit:10});
```

Python with `apify-client`:

```python
import os
from apify_client import ApifyClient
client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/skyline-tourist-webcam-directory').call(run_input={'countries':['IT'], 'maxItems':10})
items = client.dataset(run['defaultDatasetId']).list_items(limit=10).items
```

### Use with MCP

Select the Actor-specific endpoint and authenticate your client according to Apify's MCP documentation:

```bash
claude mcp add --transport http apify "https://mcp.apify.com?tools=automation-lab/skyline-tourist-webcam-directory"
```

For Claude Desktop, Cursor, and VS Code clients supporting HTTP MCP:

```json
{"mcpServers":{"apify":{"url":"https://mcp.apify.com?tools=automation-lab/skyline-tourist-webcam-directory"}}}
```

Example prompt: “Export ten Italian SkylineWebcams camera catalogue records and summarize the displayed host credits and stream observation statuses.” Country and row-limit fields determine the collection; prompt wording does not add unsupported search filters.

Discover actual tool names and schemas with scoped `tools/list`. Actor selection also exposes run/dataset helpers; it is not exactly one tool. Start an authorized run once and retain its ID, status and storage IDs (metadata, not result rows). The server waits at most `waitSecs` 0–45 seconds (default 30), so completion is not guaranteed. Configure the client request timeout above the chosen wait plus transport margin, for example 40 seconds for a 30-second wait, within the total deadline below. If a client timeout occurs before a run ID is known, report that run creation/status is uncertain; do not blindly restart. If the ID is known, recover/check that same run. If it is nonterminal, check that same run with bounded 2/4/8-second backoff capped at 10 seconds and a 120-second deadline; do not restart to poll after a client timeout. At the deadline report pending with the run ID.

After success, use `get-dataset-items` with the returned `defaultDatasetId`, explicit `limit: 20`, `offset: 0` and a `fields` projection naming `countryCode`, `countryName`, `name`, `description`, `pageUrl`, `hostCredits`, `streamUrl`, `streamStatus`, `streamObservedAt`, `scrapedAt` and `attributionNote`. Use the field-list encoding and dataset-ID argument exposed by scoped `tools/list`. Retrieve subsequent untransformed pages by source offset, at most 100 rows and 64 KiB of serialized content admitted into model context. Enforce that byte ceiling host-side, disclose omitted/oversized rows and the continuation offset, and keep full exports outside model context. If your client cannot intercept oversized responses, do not claim a hard byte guarantee. Terminal failures and any existing rows must be reported as partial.

### Limits and reliability

Country listings are finite, changing source pages. The Actor reads their current server-rendered camera cards; it does not invent pagination or guarantee exhaustive source coverage. It uses sequential HTTP requests with at most three attempts for temporary errors or empty responses. A stable HTTP 4xx or an unrecognizable page fails the run rather than producing a misleading empty success.

A missing HLS source is `not_exposed`; a failed or non-HLS manifest observation is `manifest_unavailable`. Those are useful availability observations, not proof of a page-fetch failure. URLs may expire quickly, require source headers or be unavailable from another geography. No media segments, snapshots, weather or coordinates are collected.

### Legality, responsible use and attribution

Use data only where you have permission and comply with source terms and applicable law. Public accessibility does not grant a licence to rebroadcast, record, hotlink or redistribute streams. Displayed host credits are factual source labels, not a complete determination of required attribution. Obtain permission separately for your intended media use.

The Actor does not use AI to process your input or generate output. Extraction runs on Apify; HTTP requests go to SkylineWebcams and its HLS service. Dataset and grouped files remain in your Apify storage under your account retention settings; delete them there when no longer needed. No cross-run cache is maintained. For help, open an issue on the Actor's Apify page.

This independently operated Actor is not affiliated with or endorsed by SkylineWebcams. The icon is an original generated illustration, not a source logo.

Failed operations send sanitized diagnostic input, exceptions and Actor/build/run IDs to our private GlitchTip service for repair. Secret fields and URL queries are removed; reports are retained for 30 days.

### FAQ and troubleshooting

**Can I get six to ten working streams for every country?** No. Row limits cap catalogue records, while the source controls country coverage and stream availability. Manifest observations are not playback verification.

**Can I provide country or city pages in startUrls?** No. Use country codes for discovery; explicit URLs must be English camera-detail pages. Clear countries when using them.

**Why did a stream URL stop working?** The anonymous source token can expire or depend on network/session conditions. Refresh the catalogue and treat URLs as short-lived observations.

**Why did the run fail with some rows saved?** A source page failed or changed after earlier rows were saved. Inspect logs and run status; rows are partial and should not be presented as a complete catalogue.

### Related automation

For a separate destination-data workflow, [OpenStreetMap POI Extractor](https://apify.com/automation-lab/openstreetmap-poi-extractor) exports map points of interest, not webcam streams. It is not a substitute or fallback for this source.

# Changelog

This Actor's version history is a separate document: https://apify.com/automation-lab/skyline-tourist-webcam-directory/changelog.md

# Actor input Schema

## `countries` (type: `array`):

Select up to 10 supported uppercase ISO 3166-1 alpha-2 codes. Country listing order is preserved and duplicates removed. Use countries OR camera URLs; clear this array for startUrls. TZ covers SkylineWebcams Zanzibar listings, not all Tanzania.

## `startUrls` (type: `array`):

Up to 50 exact HTTPS English www.skylinewebcams.com camera-detail URLs. No country/city/timelapse pages, query strings or other sources. Clear countries before using this route. URLs deduplicate in input order and the same per-country/global caps apply. Only url is consumed; custom method, headers, payload and userData are ignored and not applied to requests.

## `maxItems` (type: `integer`):

Global maximum unique camera records across all countries or explicit URLs; default 10, range 1–100. Earlier countries can consume the allowance. Zero/unlimited is unsupported; source availability may return fewer.

## `maxItemsPerCountry` (type: `integer`):

Maximum accepted unique camera records per country across either input route, default 10, range 1–20. Also bounded by maxItems and the current source listing; no promise of 6–10 working streams.

## Actor input object example

```json
{
  "countries": [
    "IT"
  ],
  "startUrls": [],
  "maxItems": 10,
  "maxItemsPerCountry": 10
}
```

# Actor output Schema

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

All camera fields, including observed stream URLs.

## `countries` (type: `string`):

Country objects with their webcams.

## `summary` (type: `string`):

Saved counts and manifest availability.

# 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 = {
    "countries": [
        "IT"
    ],
    "maxItems": 10,
    "maxItemsPerCountry": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/skyline-tourist-webcam-directory").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 = {
    "countries": ["IT"],
    "maxItems": 10,
    "maxItemsPerCountry": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/skyline-tourist-webcam-directory").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 '{
  "countries": [
    "IT"
  ],
  "maxItems": 10,
  "maxItemsPerCountry": 10
}' |
apify call automation-lab/skyline-tourist-webcam-directory --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/skyline-tourist-webcam-directory"
        }
    }
}
```

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/x0JJ5ygbCM1CLccL4/builds/VuTP13aQRlLWYG9nR/openapi.json
