# CNN Articles Scraper (`scrapyx/cnn-articles-scraper`) Actor

Fetches news articles from 12 CNN editions worldwide -- US, International, Espanol, Arabic, Brasil, Indonesia, Chile, Greece, Czechia, Portugal, Japan and Turkiye -- with headline, full body text, author, section, publish date and lead image, plus archive access back to 2011.

- **URL**: https://apify.com/scrapyx/cnn-articles-scraper.md
- **Developed by:** [Ibnu Adzim](https://apify.com/scrapyx) (community)
- **Categories:** News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.10 / 1,000 results

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## CNN Articles Scraper (12 Editions)

Scrapes news articles from **twelve CNN editions worldwide** in a single run —
returning the full article body, not just a headline and a link.

| | |
| --- | --- |
| **Editions** | US, International, en Español, Arabic, Brasil, Indonesia, Chile, Greece, Czechia, Portugal, Japan, Türkiye |
| **Returns** | headline, full body text, description, author(s), section, publish + modified dates, keywords, lead image, word count, language |
| **Archive depth** | back to **2015** (US/International/Español), **2011** (Chile) |
| **Method** | HTTP only — public sitemaps and RSS feeds plus each article's own page. No browser, no login, no API key |

### What you get

Every row carries the portfolio envelope — `_input`, `_source`, `_scrapedAt`,
`recordType` — plus the article fields. Three record types share the dataset:

- **`ARTICLE`** — one per article.
- **`SEARCH_SUMMARY`** — one per edition (or edition + section), carrying the
  feed's own total, how many rows were returned, which feeds were read, which
  filters were actually applied, and how many video/gallery URLs were skipped.
- **`ERROR`** — one per input that failed. **Every input maps to at least one
  row**, so a missing edition is never silently absent.

`_source` tells you which strategy produced each row: `S1-jsonld` (the article's
own JSON-LD), `S3-html` (a CSS body container, used where the edition's JSON-LD
carries no body), or `S2-sitemap` (metadata only — the detail fetch failed, and
`articleBodyFetchError` says why).

### Example input

```json
{
  "editions": ["us", "brasil", "indonesia"],
  "maxItemsPerEdition": 25,
  "includeFullBody": true,
  "keywords": ["election"]
}
```

Reaching into the archive:

```json
{
  "editions": ["us"],
  "includeArchive": true,
  "sections": ["health"],
  "dateFrom": "2020-03-01",
  "dateTo": "2020-03-31",
  "maxArchivePartitions": 3
}
```

### Editions and how deep each one goes

| Edition | Recent feed | Archive |
| --- | --- | --- |
| `us` / `intl` | ~145 articles | 2,535 monthly partitions, by section, from 2015 |
| `espanol` | ~108 | 3,435 partitions |
| `brasil` | ~500 | 501 partitions |
| `greece` | ~310 | 111 partitions |
| `chile` | ~200 | 179 monthly partitions from 2011 |
| `portugal` | ~173 | 2 partitions |
| `czech` | ~118 | 50 partitions |
| `arabic` | ~100 | 23 partitions |
| `indonesia` | ~100 per section, 9 sections | 27 partitions |
| `turkiye` | ~35 per section, 12 sections | none |
| `japan` | 30 | none |

### Sections

On **CNN Indonesia** and **CNN Türk** each section has its own feed, so a
section becomes its own query with its own summary row:

- Indonesia: `nasional`, `internasional`, `ekonomi`, `olahraga`, `teknologi`,
  `otomotif`, `edukasi`, `hiburan`, `gaya-hidup`
- Türk: `turkiye`, `dunya`, `ekonomi`, `spor`, `saglik`, `teknoloji`,
  `kultur-sanat`, `yasam`, `otomobil`, `egitim`, `magazin`

On **US / International / en Español** sections instead select which archive
partitions get fetched, and only when `includeArchive` is on. Other editions
publish one combined feed and ignore the field.

### Known limits — read before you rely on it

- **`us` and `intl` are the same backend.** `www.cnn.com` redirects to
  `edition.cnn.com`; their feeds differ by an item or two and article bodies are
  identical. Pick one unless you specifically need both hosts recorded.
- **`japan` is shallow.** CNN.co.jp publishes no sitemap at all — a 30-item RSS
  feed is the only machine-readable index that host offers, and there is no
  archive. Its articles are also genuinely short (translated wire copy, often
  under 200 characters).
- **`turkiye` date filtering is inert.** CNN Türk publishes RFC-822 dates that
  `dateFrom`/`dateTo` cannot compare, so its rows are kept rather than silently
  dropped. Filter its output downstream if you need a hard date bound.
- **Keyword filtering is client-side.** No CNN feed accepts a query parameter,
  so keywords are applied after fetching. For real server-side keyword search
  across CNN, use the companion **CNN Search Scraper**.
- **Videos and galleries are excluded.** CNN Arabic and CNN Portugal mix video
  URLs into their news sitemaps; those pages have no article body, so they are
  skipped and counted in `skippedNonArticleUrls`. Use the companion
  **CNN Videos Scraper** and **CNN Galleries Scraper** for those.
- **CNN's sitemaps contain aliased duplicates.** The same story can appear under
  two slugs (e.g. `/coronavirus-cooking` and `/coronavirus-cooking-wellness`).
  Both are real entries upstream and both are returned; de-duplication is by
  exact URL only.
- **Breaking-news stubs return a very short body.** CNN Prima News publishes
  placeholder articles ("Podrobnosti připravujeme") before the story is written.
  That is real data, not a scrape failure.

### Anti-bot

No bot mitigation was observed on the article path of any edition — all twelve
answer 200 on a cold, unproxied request. One exception:
`www.cnn.com/cnn-underscored/*` (the commerce subsection) is behind
**PerimeterX**. The built-in retry ladder rotates TLS profile and proxy exit on
each attempt and clears it without special handling.

TLS profile `chrome124` by default, rotating through `firefox133`, `safari17_0`
and `chrome99_android` on retry. Apify **Residential** proxy is the default on
the platform.

### Companion actors

- **CNN Search Scraper** — server-side keyword search across CNN.com
- **CNN Videos Scraper** — video metadata across the editions that publish it
- **CNN Galleries Scraper** — photo galleries and live stories
- **CNN Sections Scraper** — the section and tag taxonomy of each edition

# Actor input Schema

## `editions` (type: `array`):

Which CNN editions to pull from, in the SAME run. Each edition gets its own SEARCH\_SUMMARY row. `us` and `intl` share one backend and overlap almost completely -- pick one unless you specifically want both hosts. `japan` is shallow by nature (a 30-item RSS feed is the only machine-readable index that host publishes).

## `sections` (type: `array`):

Optional. On CNN Indonesia and CNN Turk each section has its own feed, so a section here becomes its own query with its own SEARCH\_SUMMARY row (Indonesia: nasional, internasional, ekonomi, olahraga, teknologi, otomotif, edukasi, hiburan, gaya-hidup. Turk: turkiye, dunya, ekonomi, spor, saglik, teknoloji, kultur-sanat, yasam, otomobil, egitim, magazin). On CNN US, International and en Espanol sections instead narrow which archive partitions are fetched, and only when 'Include archive' is on. Other editions publish one combined feed and ignore this.

## `keywords` (type: `array`):

Optional. Keep only articles whose title, feed keywords, description or body contain one of these words (case-insensitive, OR-combined). Applied AFTER fetching -- none of CNN's sitemaps or RSS feeds accepts a query parameter, so this narrows locally rather than pretending upstream filters it. Use the separate CNN Search Scraper for real server-side keyword search.

## `maxItemsPerEdition` (type: `integer`):

Cap on articles returned per edition (or per edition+section pair), applied after the date filter and before body fetching. Set to 0 for unlimited. With 'Include full article body' on, each returned article costs one extra request, so 0 against CNN Brasil's 500-article news feed means ~500 extra requests.

## `includeFullBody` (type: `boolean`):

Fetch each article's own page and extract the complete text, author, section, publish/modified dates and lead image. On by default -- the feeds themselves carry only a headline, URL and date. Turn it off for a fast metadata-only scan at one request per feed instead of one per article.

## `includeArchive` (type: `boolean`):

Also walk the edition's archive sitemap index instead of only its rolling recent feed. CNN US/International partition the archive by section and month back to 2015 (2,535 partitions); CNN Chile goes back to 2011. Editions with no archive index (Japan, Turk) report that in their SEARCH\_SUMMARY rather than failing.

## `maxArchivePartitions` (type: `integer`):

How many archive sitemap files to fetch per edition when 'Include archive' is on, newest first. The flagship archive index lists 2,535 of them; fetching all would be a multi-hour run. Ignored when 'Include archive' is off.

## `dateFrom` (type: `string`):

Optional lower bound on publish date, inclusive. On CNN US, International, en Espanol and Chile this also skips whole archive partitions whose month falls outside the range. CNN Turk publishes RFC-822 dates that this filter cannot compare, so its rows are kept rather than silently dropped.

## `dateTo` (type: `string`):

Optional upper bound on publish date, inclusive. Same partition-skipping behaviour as 'Published from'.

## `maxConcurrency` (type: `integer`):

Upper bound on requests in flight at once across all editions in this run.

## `minRequestInterval` (type: `number`):

Shared pacing floor across every request this run makes. No CNN edition sets a Crawl-delay in robots.txt; this default is this portfolio's own politeness baseline, not a site requirement. Once this cap binds, raising concurrency buys nothing.

## `proxyConfiguration` (type: `object`):

No bot mitigation was observed on any of the twelve editions during recon -- every host answered 200 cold and unproxied. Residential is still this portfolio's standard cloud default.

## Actor input object example

```json
{
  "editions": [
    "us"
  ],
  "sections": [],
  "keywords": [],
  "maxItemsPerEdition": 25,
  "includeFullBody": true,
  "includeArchive": false,
  "maxArchivePartitions": 12,
  "maxConcurrency": 5,
  "minRequestInterval": 0.25,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

## `items` (type: `string`):

One row per scraped record. See the dataset's default view for field definitions.

# 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 = {
    "editions": [
        "us"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("scrapyx/cnn-articles-scraper").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 = { "editions": ["us"] }

# Run the Actor and wait for it to finish
run = client.actor("scrapyx/cnn-articles-scraper").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 '{
  "editions": [
    "us"
  ]
}' |
apify call scrapyx/cnn-articles-scraper --silent --output-dataset

```

## MCP server setup

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

```

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/rjB0mdQENfhqLANJ9/builds/PbN3UV5nzDRH7fntB/openapi.json
