# Crypto News Scraper — 30+ Outlets, SEC/CFTC, Reddit (`yadroo/crypto-news`) Actor

Crypto headlines from CoinDesk, Cointelegraph, Decrypt, The Block, Blockworks, DL News, The Defiant and 20+ more outlets, plus SEC/CFTC releases, project blogs and r/CryptoCurrency, in one deduped JSON feed with coins mentioned. Keyword/coin/category filters, time window, full text where available.

- **URL**: https://apify.com/yadroo/crypto-news.md
- **Developed by:** [Samat Makatov](https://apify.com/yadroo) (community)
- **Categories:** News, AI, Automation
- **Stats:** 1 total users, 0 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 result items

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

**Latest crypto headlines** from CoinDesk, Cointelegraph, Decrypt, The Block, Blockworks, DL News, The Defiant, Bitcoin Magazine and 20+ more outlets, plus **SEC/CFTC press releases**, project blogs (Ethereum Foundation, Solana, Kraken) and, on request, r/CryptoCurrency — normalized into **one deduplicated list** with publish time, summary, author, categories, image and the **coins each story mentions**. Filter by keywords, coins, category and time window. Built for trading bots, research agents and alerting pipelines. No API key, no proxy, no browser.

### Use cases

- **Trading signal feed** — every 15 minutes pull `coins: ["BTC","ETH"]` from tier-1 outlets and push new ids to your model.
- **Incident monitoring** — `anyKeywords: "hack* exploit* drained breach"` + `requireCryptoContext: true` across all outlets, alert when anything matches.
- **Regulatory watch** — SEC + CFTC press releases + Cointelegraph regulation feed, keyword `crypto OR digital asset OR stablecoin`.
- **Daily digest / newsletter** — last 24 h, `maxPerSource: 3`, `dedupeTitles: true`, sorted newest first.
- **Competitor / project tracking** — `query: "coinbase"` (or a token name) with `sinceHours: 168`, or add the project's own RSS via `customFeeds`.
- **Full-text corpus for LLMs** — `includeContent: true` on outlets that ship full articles (Bitcoin Magazine, CryptoPotato, The Defiant, Cryptonews...).

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `sources` | array of ids | `["coindesk","cointelegraph","decrypt","theblock"]` | Feed ids from the table below, or group names: `all`, `default`, `news`, `tier1`, `regulators`, `blogs`, `community`, `topics`. A list field: Apify refuses any other value before the run (HTTP 400). |
| `customFeeds` | array of URLs | `[]` | Any extra http(s) RSS 2.0 / Atom URL. Source id becomes `custom:<host>` (`custom:<host>-2` for a second feed on the same host). |
| `query` | string | — | Words that must ALL appear (AND). Whole-word, case-insensitive. `*` suffix = prefix match, `"quotes"` = phrase. |
| `anyKeywords` | string | — | At least ONE must appear (OR). |
| `excludeKeywords` | string | — | Drop items containing any of these (title, summary and article body). |
| `keywordScope` | `titleSummary` | `title` | `fullText` | `titleSummary` | Where `query`/`anyKeywords` must appear. `fullText` also searches the article body when the feed has one. Exactly one of these three values. |
| `requireCryptoContext` | boolean | `false` | Keep only items whose title/summary mention crypto (coins, tokens, stablecoins, DeFi/DEX, wallets, crypto exchanges, on-chain security firms). |
| `coins` | array of text | `[]` | Keep items mentioning at least one of these coins: any of the 124 dictionary tickers, or a name from the dictionary (`bitcoin`, `polygon`, `zcash`), any letter case. An unknown value stops the run with a "did you mean" hint and costs only the start event, so a typo never switches the filter off. Corrections (`"bitcoin" read as "BTC"`) are named in the run status. |
| `categories` | string | — | Keep items whose feed categories contain any of these words (e.g. `markets regulation`). |
| `sinceHours` | integer | `24` | Time window; `0` = no time filter. Ignored when `from` is set. |
| `from`, `to` | ISO date | — | Explicit window: `YYYY-MM-DD` or `YYYY-MM-DDTHH:MM:SSZ` (a time without a zone is UTC). A date-only `from` is the start of that day, a date-only `to` its **end** (23:59:59.999 UTC), so `from = to = 2026-09-30` is the whole day. Other formats (`30.09.2026`) stop the run with an error. Feeds only hold the newest 10–200 items, so old dates return nothing. |
| `limit` | integer 1–1000 | `100` | Max items after filtering, taken from the top of the sorted list. |
| `maxPerSource` | integer | `0` | Cap per outlet (0 = no cap). |
| `sortBy` | `newest` | `oldest` | `source` | `newest` | Items without a publish date sort last (`newest`) or first (`oldest`). |
| `dedupe` | boolean | `true` | Drop repeated URLs (tracking params stripped); the source listed first in `sources` keeps the item. |
| `dedupeTitles` | boolean | `false` | Also drop near-identical titles across outlets (keeps newest). |
| `includeContent` | boolean | `false` | Add `content` (full text) when the feed provides it. |
| `fields` | array | `[]` | Output only these fields, in the order you list them; `id` is always kept (first, unless you place it). Letter case and snake\_case are read (`Title`, `published_at`); an unknown name is left out and named in the run status with a "did you mean"; a list with no known field stops the run. `content` needs `includeContent: true`. |
| `timeoutSecs` | integer 5–60 | `20` | Per-feed timeout; slow feeds are skipped and named in the run status, not a failure. |

All previous inputs (`sources`, `query`, `sinceHours`, `limit`) keep their names and meaning.

### Reference

#### Sources

| id | Outlet | Kind | Typical items/feed | Full text |
|---|---|---|---|---|
| `coindesk` | CoinDesk | news | 25 | no |
| `cointelegraph` | Cointelegraph | news | 30 | no |
| `decrypt` | Decrypt | news | 35–55 | no |
| `theblock` | The Block | news | 20 | no |
| `blockworks` | Blockworks (Atom) | news | 50 (stale, see below) | no |
| `dlnews` | DL News | news | 40 (stale, see below) | yes |
| `thedefiant` | The Defiant | news | 100 | yes |
| `bitcoinmagazine` | Bitcoin Magazine | news | 10 | yes |
| `cryptoslate` | CryptoSlate | news | 10 | yes |
| `cryptobriefing` | Crypto Briefing | news | 30 | no |
| `protos` | Protos | news | 10 | yes |
| `unchained` | Unchained | news | 10 | yes |
| `cryptopotato` | CryptoPotato | news | 36 | yes |
| `newsbtc` | NewsBTC | news | 10 | yes |
| `bitcoinist` | Bitcoinist | news | 8 | yes |
| `utoday` | U.Today | news | 90 | no |
| `ambcrypto` | AMBCrypto — **paused** (see below) | news | — | — |
| `cryptonews` | Cryptonews.com | news | 20 | yes |
| `bitcoincom` | Bitcoin.com News | news | 10 | no |
| `coingape` | CoinGape | news | 20 | no |
| `coinjournal` | CoinJournal | news | 9 | yes |
| `cryptodaily` | Crypto Daily | news | 200 | yes |
| `cryptonewsz` | CryptoNewsZ | news | 20 | yes |
| `watcherguru` | Watcher.Guru | news | 10 | yes |
| `bankless` | Bankless | research | 100 | no |
| `krakenblog` | Kraken Blog | blog | 10 | yes |
| `ethereumblog` | Ethereum Foundation Blog | blog | 600+ (whole archive) | no |
| `solananews` | Solana News | blog | 20 | no |
| `sec` | U.S. SEC press releases | regulator | 25 | no |
| `cftc` | U.S. CFTC press releases | regulator | 10 | no |
| `reddit-cryptocurrency` | r/CryptoCurrency (Atom) — **opt-in** (see below) | community | 25 | no |
| `cointelegraph-bitcoin`, `-ethereum`, `-solana`, `-defi`, `-nft`, `-regulation`, `-ai` | Cointelegraph topic feeds | news | 30 each | no |

Groups: `all` = every outlet except topic feeds, paused feeds and Reddit · `default` = coindesk, cointelegraph, decrypt, theblock · `news` = every news outlet except paused ones · `tier1` = coindesk, cointelegraph, decrypt, theblock, thedefiant, cryptoslate, cryptobriefing, bitcoinmagazine, cryptopotato, bitcoincom · `regulators` = sec, cftc · `blogs` = bankless, krakenblog, ethereumblog, solananews · `community` = reddit-cryptocurrency · `topics` = the 7 Cointelegraph tag feeds.

**Paused: `ambcrypto`.** AMBCrypto answered HTTP 403 to every automated request in 25 of 25 runs (25.09–02.10.2026). This actor does not work around blocks (no proxies, no browser disguise), so the feed is paused: it is in no group, and a run that names it fetches nothing from it and says so in its status. The id stays valid, so saved inputs keep working.

**Opt-in: `reddit-cryptocurrency`.** Reddit's Data API terms ask automated clients for registered OAuth access, which this actor does not use. The feed is no longer part of `all`; it is read only when you name it (the id or the `community` group). Check that your use fits Reddit's terms.

**Blocked now and then: `krakenblog`.** Kraken's blog sometimes answers 403 from cloud IPs. Such a 403 is not retried; the run names the feed in its status and `SUMMARY` and returns the other feeds' items.

Stale feeds (checked 27.09.2026): `blockworks` last published to its feed on 2026-01-07 and `dlnews` on 2026-05-07. Both still answer with valid XML, so they are kept as ids and in `all`/`news` in case the outlets resume, but they are no longer part of `tier1` — a 24 h window over them returns nothing. Any feed whose newest item is more than 30 days old is flagged with a warning in the log and `stale: true` in `SUMMARY`.

#### Coin dictionary (`coins` filter and `coinsMentioned` field)

BTC, ETH, SOL, XRP, BNB, DOGE, ADA, TRX, AVAX, LINK, DOT, MATIC, TON, SHIB, LTC, BCH, UNI, AAVE, ARB, OP, SUI, APT, NEAR, ATOM, HYPE, PEPE, WIF, USDT, USDC, DAI, XLM, XMR, FIL, ICP, ENA, ONDO, WLD, TAO, RENDER, AERO, ZEC, ETC, BSV, WBTC, STETH, HBAR, VET, ALGO, KAS, CRO, MNT, IMX, INJ, STX, SEI, TIA, GRT, FET, JUP, PYTH, BONK, FLOKI, TRUMP, WLFI, USDE, PYUSD, FDUSD, USD1, LEO, OKB, BGB, KCS, XDC, QNT, EOS, XTZ, THETA, SAND, MANA, AXS, CRV, LDO, JTO, PENDLE, ENS, STRK, ZK, W, RAY, VIRTUAL, IP, BERA, PI, OM, FLR, NEXO, IOTA, HNT, CFX, EGLD, KAIA, AR, ROSE, CAKE, GALA, DYDX, 1INCH, COMP, SNX, ZRO, EIGEN, MORPHO, S, PENGU, FARTCOIN, SPX, POPCAT, XAUT, PAXG, NEO, XPL, LINEA, MON, PUMP. Each ticker matches its full name and common aliases as whole words (`ETH` = ethereum / eth / ether; `MATIC` = polygon / matic / pol token; `ZEC` = zcash / zec). Longer names win: "Bitcoin Cash" tags BCH only, "Ethereum Classic" ETC only. Tickers that are everyday words (ETC, VET, ALGO, LEO, IOTA, SPX, TRUMP…) match by name only (`official trump`, `$trump`, `algorand`…). The `coins` input accepts each ticker and each of these names (`"zcash"` = ZEC, `"polygon"` = MATIC); nothing else is guessed. For any other asset use `query` or `anyKeywords`.

#### Categories by outlet (examples)

CoinDesk: Markets, Finance, Policy, Tech, News · The Block: Markets, Companies, Policy, Regulation, Exchanges · Cointelegraph: Latest News, Markets, Magazine · Blockworks: Policy, The Breakdown · Decrypt: Coins, Business, Technology. Categories are free-form per outlet; `categories` does a case-insensitive contains match.

### Examples

**Hack / exploit alerting across the whole industry (last 6 h)**

```json
{ "sources": ["all"], "anyKeywords": "hack* exploit* drained breach \"rug pull\"", "requireCryptoContext": true, "sinceHours": 6, "dedupeTitles": true, "limit": 50 }
```

**BTC + ETH headlines from tier-1 outlets for a trading model**

```json
{ "sources": ["tier1"], "coins": ["BTC", "ETH"], "sinceHours": 3, "fields": ["source", "title", "url", "publishedAt", "coinsMentioned"] }
```

**Regulatory watch (SEC, CFTC, Cointelegraph regulation feed)**

```json
{ "sources": ["regulators", "cointelegraph-regulation"], "anyKeywords": "crypto stablecoin \"digital asset\" exchange token", "sinceHours": 168 }
```

**Balanced daily digest**

```json
{ "sources": ["all"], "sinceHours": 24, "maxPerSource": 3, "dedupeTitles": true, "excludeKeywords": "sponsored \"press release\" giveaway", "limit": 60 }
```

**Full-text corpus about a project, plus its own blog**

```json
{ "sources": ["all"], "query": "hyperliquid", "sinceHours": 720, "includeContent": true, "customFeeds": ["https://hyperliquid.substack.com/feed"] }
```

### Output

One item per article:

```json
{
  "id": "5b303aa0",
  "source": "theblock",
  "sourceName": "The Block",
  "sourceKind": "news",
  "feedUrl": "https://www.theblock.co/rss.xml",
  "title": "CryptoQuant says bitcoin must clear resistance at $81,700 to confirm new bull market",
  "url": "https://www.theblock.co/news/markets/2026-09-12-cryptoquant-bitcoin-resistance-support-levels-414519",
  "summary": "Bitcoin's outlook remains bullish, but it needs to clear a significant range of resistance levels stretching to $88,700, CryptoQuant said.",
  "publishedAt": "2026-09-12T21:39:49.000Z",
  "author": "Yogita Khatri",
  "categories": ["Markets", "News"],
  "image": "https://www.tbstat.com/wp/uploads/2026/04/20260410_Bitcoin_News-1200x675.jpg",
  "coinsMentioned": ["BTC"],
  "fetchedAt": "2026-09-12T23:33:32.292Z"
}
```

| Field | Type | Meaning |
|---|---|---|
| `id` | string | Stable 8-hex hash of the canonical URL — use it to detect new items between runs. |
| `source`, `sourceName`, `sourceKind` | string | Feed id, display name, `news` / `research` / `blog` / `regulator` / `community`. |
| `feedUrl` | string | The RSS/Atom URL the item came from. |
| `title`, `url`, `summary` | string | Summary is plain text (HTML stripped), max 1000 chars. |
| `content` | string | null | Full article text, only with `includeContent: true` and only if the feed ships it. |
| `publishedAt` | ISO string | null | From `pubDate` / `published` / `updated`. |
| `author` | string | null | |
| `categories` | string\[] | Feed categories / tags (max 12). |
| `image` | string | null | First media/enclosure image. |
| `coinsMentioned` | string\[] | Tickers from the dictionary found in title + summary. |
| `fetchedAt` | ISO string | Run time. |

Every run ends with a **status message** that says how many items were saved from how many feeds and names every feed that failed, was skipped (paused, or not read before a stop) or is stale, plus every input correction. The key-value store record `SUMMARY` holds the same as data: per-feed stats (`parsed`, `kept`, `newestItem`, `stale`, `error`, `notRead`), `delivered`, `matched`, `feedsFailed`, `feedsNotRead`, `pausedSources`, `notes`, the applied filters (`sinceIso`, `untilIso`) and `stoppedBy` (`limit`, `timeout` or null).

### Use it from code / agents

```bash
curl -X POST "https://api.apify.com/v2/acts/yadroo~crypto-news/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"sources":["tier1"],"coins":["BTC"],"sinceHours":6}'
```

```js
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('yadroo/crypto-news').call({ sources: ['all'], anyKeywords: 'hack* exploit*', sinceHours: 12 });
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

```python
from apify_client import ApifyClient
client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("yadroo/crypto-news").call(run_input={"sources": ["regulators"], "sinceHours": 168})
items = client.dataset(run["defaultDatasetId"]).list_items().items
```

MCP: add `https://mcp.apify.com` to your agent (Claude, Cursor, custom) and call the `yadroo/crypto-news` tool with the same JSON input.

### Pricing

Pay per event: **$0.001 per run start + $0.0005 per news item returned**. Bronze −10 %, Silver −20 %, Gold and above −30 % on the item price; the start event is the same on every plan; platform usage is included. A default run (4 outlets, last 24 h) returns ~20–40 items ≈ $0.01–0.02. An `all`-sources 24 h digest is typically 150–300 items ≈ $0.08–0.15. Use `limit`, `maxPerSource` and filters to control cost — you only pay for items that pass the filters.

**Max cost per run** is respected: the run reads how many items your limit pays for, stores exactly that many and ends with *"Stopped at your spending limit: N rows delivered."* A limit that covers no item reads no feed at all.

### Limits & FAQ

- **Freshness** — feeds are fetched live on every run; outlets update their RSS within minutes of publishing. Some blogs lag.
- **History** — RSS only carries the latest 8–200 items per outlet (see table). For archives use `includeContent`-free runs on a schedule and store the ids.
- **Errors** — a feed that times out, is blocked (401/403/404 are answers and are not retried) or returns non-XML is skipped and named in the run status and `SUMMARY`; 429 and 5xx answers are retried after the site's `Retry-After` (or 1.5 s, 3 s). The run fails only if *every* feed failed.
- **Politeness** — different outlets are read in parallel, but the feeds of one host (Cointelegraph serves 8) are read one after another, 1 s apart.
- **Run timeout** — near the run's timeout the actor stops starting feeds, saves the items it has and ends with *"Stopped before the run timeout"* and the feeds it did not read. A normal run takes 5–20 s.
- **Items without a date** — a few feeds leave out the publish date on some items; those items are kept by `sinceHours`/`from`/`to` (there is nothing to compare) and carry `publishedAt: null`.
- **Volume per window** — an outlet publishes 5–20 stories a day and far fewer at weekends, so a narrow run (one coin, a few outlets, `sinceHours: 24`) can legitimately return a handful of rows. Widen `sinceHours`, add outlets or use `sources: ["all"]` for a fuller picture.
- **Feeds that stop** — outlets sometimes abandon their RSS while still serving it (Blockworks since January 2026, DL News since May 2026). A feed with no item newer than 30 days is named in the run status and has `stale: true` in `SUMMARY`; the bundled groups are re-checked when that happens.
- **Feeds that block** — AMBCrypto is paused and Reddit is opt-in (see Reference → Sources). A source that adds an anti-bot wall is paused, not fought.
- **Keyword matching** — whole words, case-insensitive, in the title and summary by default (`keywordScope`). A trailing `*` is a prefix: `hack*` matches hacked, hackers, hacking, but also hackathon or the auditor Hacken. For tight alerts list the forms (`hack hacked hacks hacker hackers hacking`). Crypto outlets also publish AI-security, stock and casino stories: `requireCryptoContext: true` drops the ones that don't mention crypto in the title or summary. Before 18.09 keywords were matched in the article body too, which pulled in stories that used "breach" or "hack" only in passing; use `keywordScope: "fullText"` for that behaviour.
- **SEC / CFTC feeds** — these are general press-release feeds. In a typical week 1–2 of 25 SEC releases mention crypto, and the CFTC feed carries titles only (no summary), so crypto keywords rarely match there. That reflects the source, not a filtering bug. Leave `requireCryptoContext` off and use keywords such as `crypto* token* "digital asset" stablecoin*`.
- **Duplicates** — the same story is often covered by several outlets; `dedupe` removes identical URLs, `dedupeTitles` removes same-title coverage.
- **Language** — all bundled feeds are English.
- **Terms** — only public RSS/Atom feeds are read; content is used as the publishers expose it (title, summary, link). Respect each outlet's terms when redistributing full text.
- **Roadmap** — sentiment scoring per item, more regional outlets, Google News fallback for outlets without RSS.

***

Made by **Yadroo** — more data actors for agents: [crypto-sentiment](https://apify.com/yadroo/crypto-sentiment) · [coingecko-markets](https://apify.com/yadroo/coingecko-markets) · [defillama-protocols](https://apify.com/yadroo/defillama-protocols) · [x402-endpoints](https://apify.com/yadroo/x402-endpoints) · [google-news-search](https://apify.com/yadroo/google-news-search) · [rss-to-json](https://apify.com/yadroo/rss-to-json)

# Actor input Schema

## `sources` (type: `array`):

Feed ids or group names from the list (README → Sources has the table). Groups: all = every outlet except topic feeds and Reddit; default = coindesk, cointelegraph, decrypt, theblock; news; tier1; regulators = SEC + CFTC; blogs; community = Reddit (opt-in); topics = 7 Cointelegraph tag feeds. ambcrypto is paused (it blocks automated requests): naming it fetches nothing. Values outside the list are refused by Apify before the run.

## `customFeeds` (type: `array`):

Extra RSS 2.0 / Atom feed URLs to include (any crypto blog, Substack, project announcements). Source id becomes custom:<host>.

## `query` (type: `string`):

Words that must ALL appear (AND). Example: etf approval. Empty = no filter.

## `anyKeywords` (type: `string`):

Words of which at least ONE must appear (OR). Example: hack\* exploit\* drained lawsuit.

## `excludeKeywords` (type: `string`):

Drop items containing any of these words (checked in title, summary and the full text the feed provides). Example: sponsored "press release" giveaway.

## `keywordScope` (type: `string`):

Where "All words" / "Any words" must appear. Title + summary (default) = the text you see in the output. Full text also searches the article body when the feed carries one, which finds more but also stories that only mention the word in passing ("breach of duty", "Hacksaw Gaming").

## `requireCryptoContext` (type: `boolean`):

Keep only items whose title or summary mentions crypto: coins, tokens, stablecoins, DeFi/DEX, wallets, exchanges like Binance/Coinbase, on-chain security firms. Drops AI-security, stock and casino stories that crypto outlets also publish. Recommended for incident alerts (hack\*, exploit\*). Leave off for SEC/CFTC feeds without keywords: most of their releases are not about crypto.

## `coins` (type: `array`):

Keep only items that mention at least one of these coins. Tickers or names, any letter case: BTC, eth, Solana, polygon. 124 tickers are known (README → Coin dictionary); an unknown one stops the run with a "did you mean" hint, so a typo never turns the filter off. Every item gets coinsMentioned either way. For other assets use query or anyKeywords.

## `categories` (type: `string`):

Keep items whose feed categories/tags contain any of these words, e.g. "markets regulation". Categories differ per outlet (see README).

## `sinceHours` (type: `integer`):

Only items published in the last N hours. 0 = no time filter (returns whatever the feeds currently hold, usually 10-100 items per outlet). Ignored when "from" is set.

## `from` (type: `string`):

Earliest publish time: YYYY-MM-DD (start of that day, UTC) or YYYY-MM-DDTHH:MM:SSZ; a time without a zone is UTC. Overrides sinceHours. RSS feeds hold only their latest 10-200 items, so old dates return nothing. Other formats stop the run with an error.

## `to` (type: `string`):

Latest publish time, inclusive: YYYY-MM-DD means the END of that day (23:59:59.999 UTC), or give an exact time as in "from".

## `limit` (type: `integer`):

Maximum number of items to return after filtering and dedupe. Your max cost per run can stop the run earlier; the status then says so.

## `maxPerSource` (type: `integer`):

Cap items per outlet to balance the digest (0 = no cap).

## `sortBy` (type: `string`):

Ordering of the output.

## `dedupe` (type: `boolean`):

Drop repeated URLs (tracking params stripped) — happens when an outlet is selected twice via a group and a topic feed.

## `dedupeTitles` (type: `boolean`):

Also drop stories with the same normalized title across outlets (syndicated/duplicate coverage). Keeps the newest.

## `includeContent` (type: `boolean`):

Add a content field with the full article text when the feed provides it (content:encoded / Atom content). Many outlets only publish a summary.

## `fields` (type: `array`):

Output only these fields, in this order (id is always kept). Available: source, sourceName, sourceKind, feedUrl, title, url, summary, content (needs includeContent), publishedAt, author, categories, image, coinsMentioned, fetchedAt. Letter case and snake\_case are fine; an unknown name is left out and named in the run status, and a list with no known field stops the run.

## `timeoutSecs` (type: `integer`):

Per-feed timeout. Feeds slower than this are skipped and named in the run status.

## Actor input object example

```json
{
  "sources": [
    "coindesk",
    "cointelegraph",
    "decrypt",
    "theblock"
  ],
  "customFeeds": [],
  "keywordScope": "titleSummary",
  "requireCryptoContext": false,
  "coins": [],
  "sinceHours": 24,
  "limit": 100,
  "maxPerSource": 0,
  "sortBy": "newest",
  "dedupe": true,
  "dedupeTitles": false,
  "includeContent": false,
  "fields": [],
  "timeoutSecs": 20
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `summary` (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 = {
    "sources": [
        "coindesk",
        "cointelegraph",
        "decrypt",
        "theblock"
    ],
    "customFeeds": [],
    "coins": [],
    "fields": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("yadroo/crypto-news").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 = {
    "sources": [
        "coindesk",
        "cointelegraph",
        "decrypt",
        "theblock",
    ],
    "customFeeds": [],
    "coins": [],
    "fields": [],
}

# Run the Actor and wait for it to finish
run = client.actor("yadroo/crypto-news").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 '{
  "sources": [
    "coindesk",
    "cointelegraph",
    "decrypt",
    "theblock"
  ],
  "customFeeds": [],
  "coins": [],
  "fields": []
}' |
apify call yadroo/crypto-news --silent --output-dataset

```

## MCP server setup

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

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/REUNA83owEeJ9z0i8/builds/DGnga4fw18QD7gRiM/openapi.json
