# Google News Scraper: Articles by Keyword, Topic & Country (`hyperbach/google-news-scraper`) Actor

Scrape Google News articles by keyword or topic in any of 84 regions and languages: title, publisher name and site, date, Google News link, the publisher's article URL on request, and related coverage. Time filters (1 hour to 1 year), several keywords per run, past 100 per keyword. Misses free.

- **URL**: https://apify.com/hyperbach/google-news-scraper.md
- **Developed by:** [Hyperbach](https://apify.com/hyperbach) (community)
- **Categories:** News, SEO tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.00 / 1,000 articles

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

## Google News Scraper: Articles by Keyword, Topic & Country

**Google News articles, logged out: search keywords or Google News topics in, one row per article out — the title, the publisher's name and site, the date published, the Google News link, the publisher's own article URL on request, and the other articles Google lists on the same story — in any of 84 regions and languages, with a time frame from the last hour to the last year, several keywords in one run, and past Google's 100 a feed one day at a time.** One free row per keyword or topic carries a completeness verdict: COMPLETE (the feed's own end), CAPPED (your limit), TRUNCATED (Google holds more than its feeds serve) or PARTIAL. No login, no API key, no browser, proxies handled for you.

**$4.00 per 1,000 `article` rows on the Free plan, $3.40 on Starter.** A run start is $0.002. The default input returns about 50 rows for about $0.202. A value that names nothing is a free row that says why.

### Why this Google News scraper

- **Keywords and topics, any edition.** Give search words (`bitcoin`, `"electric vehicles" OR EV`, `tesla site:reuters.com`) and Google News sections (`WORLD`, `BUSINESS`, `TECHNOLOGY` … `TOP_STORIES`) or a topic or section URL copied from news.google.com. Pick one of 84 Google News editions (`US:en`, `GB:en`, `DE:de`, `FR:fr`, `JP:ja`, `BR:pt-419` …); a topic URL is read in its own edition.
- **Time filters.** `timeframe` = `1h`, `1d`, `7d`, `30d` or `1y` keeps a keyword's articles in the last hour, day, week, month or year; Google's own `after:YYYY-MM-DD` and `before:YYYY-MM-DD` in a keyword set your own dates. Schedule `1h` runs for hourly monitoring.
- **Past Google's 100.** Google's feed serves about 100 articles a keyword. With a larger `maxArticles` (or 0) the run reads the keyword one day at a time, newest day first, back to the time frame's start: on our test eight days of "artificial intelligence" gave 777 distinct articles where the feed gave 100 (2026-10-29). A day that Google fills to its own limit makes the verdict TRUNCATED, so you know when more exist.
- **The publisher's URL, on request.** Every row has the publisher's name and site and the Google News link; `decodeUrls` adds the publisher's own article URL (`url`), resolved from Google's link without a browser (100 of 100 on our deployed test, 2026-10-29; two more requests an article, so 100 articles take about 30 s instead of 2). The same price either way.
- **The story's other coverage.** When Google groups several articles into one story, `related_articles` lists the others (title, publisher, link): one row, the whole cluster.
- **Honest runs.** A keyword with no article is a free `no_results` row (two exits agreed), an unknown topic a free `not_found` row, a value that is not a keyword or topic a free `invalid` row, a repeated value a free `duplicate` row. Every input gets a row with its verdict; an article two keywords list is charged once.
- **Fast and light.** Plain HTTP on Google News' own RSS feeds: about 0.3 KB an article on the wire, 100 articles a call. On our deployed test 100 articles of one keyword took 1.4 s of reading, 4.7 s in all (2026-10-29).

### Who it's for

- **PR, brand and communications teams** — every article that names a brand, a client or a person, read every hour or day with `1h` / `1d`, the publisher and the date on each row, into a sheet, Slack or a dashboard.
- **Analysts, traders and researchers** — the coverage of a company, a market or a topic over days or months (`after:` / `before:` or a time frame past the feed's 100), with each article's publisher and date and the story clusters Google built.
- **Data and AI teams** — typed rows keyed by `article_id`, the publisher's article URL for a later crawl (`decodeUrls`), a free row per keyword with the verdict and a run summary to check a pipeline against.

### Quick start

**The 50 newest articles about bitcoin**

```json
{
  "keywords": [
    "bitcoin"
  ],
  "maxArticles": 50
}
```

**Three keywords in the last 24 hours, with the publishers' URLs**

```json
{
  "keywords": [
    "tesla",
    "spacex",
    "nvidia"
  ],
  "timeframe": "1d",
  "maxArticles": 20,
  "decodeUrls": true
}
```

**German business and technology news**

```json
{
  "topics": [
    "BUSINESS",
    "TECHNOLOGY"
  ],
  "regionLanguage": "DE:de"
}
```

**Every article of a week, past the feed's 100**

```json
{
  "keywords": [
    "artificial intelligence"
  ],
  "timeframe": "7d",
  "maxArticles": 0
}
```

### Output

One row per article (and one free row per keyword or topic):

| field | meaning |
|---|---|
| `row_type` | `article` (one article, charged) or `input` (the keyword's or topic's row with the walk's verdict; free). |
| `input_index` | The 1-based position of the input in its list (`keywords` or `topics`). |
| `input_value` | The keyword or topic as you gave it. |
| `input_kind` | What the input is: `keyword`, `topic`, `top_stories`, `topic_url`, `invalid` or `duplicate`. |
| `status` | An input row: `ok`, `no_results`, `not_found`, `invalid`, `duplicate`, `failed` or `not_read` (see the FAQ). An article row: `ok`. |
| `status_detail` | Why, in words, when the status is not `ok`. |
| `scraped_at` | When the row was read (ISO 8601, UTC). |
| `position` | The article's place among this input's delivered articles (1 = first). |
| `title` | The article's headline, without the publisher's name Google appends. |
| `source_name` | The publisher's name, as Google News shows it. |
| `source_url` | The publisher's site (its home page). |
| `published_at` | When the article was published (ISO 8601, UTC). |
| `url` | The publisher's own article URL, when `decodeUrls` is on (see `url_status`). |
| `url_status` | `decoded` (`url` holds the publisher's URL), `not_asked` (`decodeUrls` off) or `failed` (Google did not resolve this link). |
| `google_news_url` | The article's Google News link (it leads to the publisher's article). |
| `article_id` | Google News' id of the article (the key: one row per id a run). |
| `related_articles` | The other articles Google lists on the same story: one object per article with `title`, `source_name` and `google_news_url` (empty when the story has one article). |
| `related_count` | How many articles `related_articles` holds. |
| `feed_position` | The article's place in the Google News feed it came from. |
| `window` | The day (YYYY-MM-DD) whose feed gave the article, when the run read past the first feed one day at a time; empty for the first feed. |
| `first_seen_at` | With `onlyNew`: the day this memory first saw the article. |
| `last_seen_at` | With `onlyNew`: the day this memory last saw the article. |
| `times_seen` | With `onlyNew`: how many runs of this memory saw the article. |
| `region_language` | The Google News edition read (`US:en` …). |
| `timeframe` | A keyword's time frame (`all`, `1h`, `1d`, `7d`, `30d`, `1y`); empty for a topic. |
| `feed_url` | An input row: the Google News feed the input's first call read. |
| `articles_delivered` | An input row: the article rows delivered for this input. |
| `feeds_read` | An input row: how many feeds were read (the first feed and the day windows). |
| `skipped_seen` | An input row, with `onlyNew`: articles an earlier run of this memory delivered, skipped free (not decoded, no cap slot taken). |
| `verdict` | An input row: `COMPLETE` (the feed's own end, or every day of the time frame read), `CAPPED` (your cap), `TRUNCATED` (Google held more than its feeds serve) or `PARTIAL` (a refusal or the time limit). |
| `verdict_detail` | An input row: the verdict in words — articles delivered, feeds and day windows read, articles skipped, why the walk stopped. |

Example record:

```json
{
  "row_type": "article",
  "input_index": 1,
  "input_value": "climate change",
  "input_kind": "keyword",
  "status": "ok",
  "status_detail": null,
  "scraped_at": "2026-10-29T10:45:09Z",
  "position": 3,
  "title": "Climate change should be declared 'global health emergency' as health harms and heat deaths accelerate",
  "source_name": "DW.com",
  "source_url": "https://www.dw.com",
  "published_at": "2026-10-28T05:54:44Z",
  "url": "https://www.dw.com/en/experts-urge-global-health-emergency-as-climate-harms-accelerate/a-79773232",
  "url_status": "decoded",
  "google_news_url": "https://news.google.com/rss/articles/CBMingFBVV95cUxNZ2JpQmRMQzVMQW1SdG1vdTFzZFZTVWdIN3A4ZUhDczhUeUpSY2lGSFc3b01LY043T3R1R1BRZDFyQkFQZ2RIakFPenVjd1RoSmFJdlp1YU5CZ3BMa1VfaHV6N2RISl9IeFRQNDhCU3pWVWlDc1NZM3Bxd3phamxQTThPb2pJSUdVN3ZkTUxWNnE1Q0Nwdm1qM19uNEpXZ9IBngFBVV95cUxOVTc0czlZQWZUQ3VKbGhHUHBYUk82aGV2aXNqVXNKMU9rRXV2ODYyV3NmMGE3MkNWNWgzZkxGajh3dHNGQUl1NHd4N203TWJqdThIejFxS2xvX1NTLVdXcTdXQ0RTcUtucm9wS1dQelUtOVZoRlhmZVpRbkhSNXAyM1Byb29SZlJ6dlVqWk1Jakx4ZmtzWkZ6T2QyTFpZdw?oc=5",
  "article_id": "CBMingFBVV95cUxNZ2JpQmRMQzVMQW1SdG1vdTFzZFZTVWdIN3A4ZUhDczhUeUpSY2lGSFc3b01LY043T3R1R1BRZDFyQkFQZ2RIakFPenVjd1RoSmFJdlp1YU5CZ3BMa1VfaHV6N2RISl9IeFRQNDhCU3pWVWlDc1NZM3Bxd3phamxQTThPb2pJSUdVN3ZkTUxWNnE1Q0Nwdm1qM19uNEpXZ9IBngFBVV95cUxOVTc0czlZQWZUQ3VKbGhHUHBYUk82aGV2aXNqVXNKMU9rRXV2ODYyV3NmMGE3MkNWNWgzZkxGajh3dHNGQUl1NHd4N203TWJqdThIejFxS2xvX1NTLVdXcTdXQ0RTcUtucm9wS1dQelUtOVZoRlhmZVpRbkhSNXAyM1Byb29SZlJ6dlVqWk1Jakx4ZmtzWkZ6T2QyTFpZdw",
  "related_articles": [
    {
      "title": "Climate change is a 'global health emergency' and the harms are accelerating, Lancet report warns",
      "source_name": "ABC News - Breaking News, Latest News and Videos",
      "google_news_url": "https://news.google.com/rss/articles/CBMiqgFBVV95cUxNR0RmVVk5R0R1SlZ5bmxUd0kzbW43UDl0ckZYMUprTl9aMzZ3Mzl1NkM5bUdaUTlkMk51eUludThnbFAydUFfekFtMUcwT2pjVUVGS1YtN1JKS0ZGMjRJMUVOTzJna2ZzOXJIb2NHRE9YMmlUSXI0ZTRRaWlMeGxCa2dPdGNzZGFCUWVqRmR5aHBuU1hRc2VCc0FpUnFwRGVmM2lCRnJBaXNUUdIBrwFBVV95cUxOQVdGZGZhNXpYX1dYYVJkWVpEVXQ3cUF3aVF0TDhLQWJCZU9zWHhBb0dIa2NMTk5SWC1fem9OV3FBVWI2VjI1eEJ5SFhjZEtLano0TzlWT1hxVFpqYlNvbF9lNnpfQV9pNGpud1VjNWRsb2JyR3c1M1hGdTY5bnZsWjljUmlWcnQ1eDJ1NDdUNjh6VEFyUUNlcVdBZk14YXFNTDdVT2p2YmR6QlVwT3VF?oc=5"
    },
    {
      "title": "Why the WHO must declare climate change a public health emergency",
      "source_name": "Phys.org",
      "google_news_url": "https://news.google.com/rss/articles/CBMidkFVX3lxTE9LUDFSY2RCWFpZdFZFWm02SXVPYkJXYTlqbWgzOG52NmpQUGlYbkdNRWhEaHhHY2xKWXFqdkNza09HeDA2Z3NyTVNObHNIOS1jSFRNZWw5Nml1UjNLbzZDTjRyV3QyZGY3QWkybWoxNF8xS2ZKQXc?oc=5"
    }
  ],
  "related_count": 2,
  "feed_position": 3,
  "window": null,
  "first_seen_at": null,
  "last_seen_at": null,
  "times_seen": null,
  "region_language": "US:en",
  "timeframe": "all",
  "feed_url": null,
  "articles_delivered": null,
  "feeds_read": null,
  "skipped_seen": null,
  "verdict": null,
  "verdict_detail": null
}
```

### Pricing

**Pay for the articles a run delivers**, plus one run start; no platform usage is billed to you. The article price falls with your Apify plan.

| event | unit | Free | Starter | Scale | Business |
|---|---|---|---|---|---|
| Article (`article`) | per 1,000 | $4.00 | $3.40 | $2.80 | $1.00 |
| Run start (`start`) | per run | $0.002 | $0.002 | $0.002 | $0.002 |

An article is **$4.00 per 1,000** on the Free plan ($0.004 an article), with or without the decoded publisher URL. Each run that delivers a charged article also pays the **run start, $0.002 once**; a run that delivers no charged article pays nothing at all. So 100 articles of one keyword cost $0.402 on the Free plan; several keywords in one run share one start. The free row of every keyword and topic, a keyword with no article (`no_results`), an unknown topic (`not_found`), a value that is not a keyword or topic (`invalid`), a repeated value (`duplicate`), a value left at the charge limit or the time limit (`not_read`) and a refusal the run could not pass (`failed`) are never charged. An article is charged once a run, even when two keywords list it. A run that stops early (a timeout, an abort) is charged for the articles it delivered. `maxItems` counts the charged rows; before the first request the log names the price of each row at your plan and the most the run can cost. Enterprise plans have their own rates: the Actor's Pricing tab shows the price for your plan.

### Usage patterns

- **A schedule** — Save a task with `onlyNew` (and a `stateStoreName` to name the memory), set `timeframe` to the task's interval (`1h` for an hourly task, `1d` for a daily one) and schedule it. The first run delivers the articles of its feeds; each later run delivers only the articles an earlier run of that memory did not, and skips the rest free, undecoded — the input row counts them in `skipped_seen`. A skipped article takes no `maxArticles` slot: with a time frame wider than the schedule and a full feed, the walk reads the day windows for articles the memory never received. Every delivered row of a monitored run carries `first_seen_at`, `last_seen_at` and `times_seen`. Two tasks with the same memory name share what they delivered; without a name, the memory is derived from the keywords, topics and edition, so the same inputs find the same memory.
- **Keywords and topics** — `keywords` takes search words, one search per line; Google's operators work inside a line (`site:`, `OR`, `-word`, quotes, `when:`, `after:`, `before:`). `topics` takes the section names `WORLD`, `NATION`, `BUSINESS`, `TECHNOLOGY`, `ENTERTAINMENT`, `SPORTS`, `SCIENCE`, `HEALTH`, `TOP_STORIES`, or a topic or section URL from news.google.com (open a topic in your browser and copy its address).
- **What a row is** — `row_type` = `article`: one article with its record; `related_articles` holds one object per other article of the same story. `row_type` = `input`: the free row of one keyword or topic — `articles_delivered`, `feeds_read`, `feed_url`, the `verdict` with its `verdict_detail`, and the `status` with its reason.
- **How far a keyword goes** — `maxArticles` = 100 (the default) reads one feed: about the 100 articles Google ranks first in the time frame. A larger number, or 0, reads one day at a time after a full feed, newest day first, back to the start of `timeframe` (`7d`, `30d`, `1y`; `all` until 60 empty days in a row); `1h` and `1d` are one feed. A topic's feed is its own list (about 40-70 articles). `maxItems` caps the charged rows of the whole run. The input row's `verdict` says where the walk stopped and why.

### Input configuration

| field | type | default | what it does |
|---|---|---|---|
| `keywords` | `array` |  | Search words, one search per line (`bitcoin`, `artificial intelligence`, `"electric vehicles" OR EV`). Google's own operators work: `site:reuters.com`, `OR`, `-word`, quotes, and `when:`, `after:YYYY-MM-DD`, `before:YYYY-MM-DD` for your own dates (then `timeframe` is not added to that line). Up to 1,000 keywords and topics a run. A line given twice gets a free `duplicate` row. |
| `topics` | `array` |  | Google News sections: `WORLD`, `NATION`, `BUSINESS`, `TECHNOLOGY`, `ENTERTAINMENT`, `SPORTS`, `SCIENCE`, `HEALTH`, `TOP_STORIES` (the front page), or a topic or section URL copied from news.google.com (`https://news.google.com/topics/…`, read in the URL's own region and language). A topic's feed is its own list (about 40-70 articles); `timeframe` does not apply to it. |
| `regionLanguage` | `US:en` / `SK:sk` / `AU:en` / `BW:en` / `CA:en` / `ET:en` / `GH:en` / `IN:en` / `ID:en` / `IE:en` / `IL:en` / `KE:en` / `LV:en` / `MY:en` / `NA:en` / `NZ:en` / `NG:en` / `PK:en` / `PH:en` / `SG:en` / `ZA:en` / `TZ:en` / `UG:en` / `GB:en` / `ZW:en` / `ID:id` / `CZ:cs` / `DE:de` / `AT:de` / `CH:de` / `AR:es-419` / `CL:es-419` / `CO:es-419` / `CU:es-419` / `ES:es` / `US:es-419` / `MX:es-419` / `PE:es-419` / `VE:es-419` / `BE:fr` / `CA:fr` / `FR:fr` / `MA:fr` / `SN:fr` / `CH:fr` / `IT:it` / `LV:lv` / `LT:lt` / `HU:hu` / `BE:nl` / `NL:nl` / `NO:no` / `PL:pl` / `BR:pt-419` / `PT:pt-150` / `RO:ro` / `SI:sl` / `SE:sv` / `VN:vi` / `TR:tr` / `GR:el` / `BG:bg` / `RU:ru` / `UA:ru` / `RS:sr` / `UA:uk` / `IL:he` / `AE:ar` / `SA:ar` / `LB:ar` / `EG:ar` / `IN:mr` / `IN:hi` / `BD:bn` / `IN:bn` / `IN:ta` / `IN:te` / `IN:ml` / `TH:th` / `CN:zh-Hans` / `TW:zh-Hant` / `HK:zh-Hant` / `JP:ja` / `KR:ko` | `"US:en"` | The Google News edition to read: country and language, as Google names it (`US:en` is the United States in English, `DE:de` Germany in German, `BR:pt-419` Brazil in Portuguese). |
| `timeframe` | `all` / `1h` / `1d` / `7d` / `30d` / `1y` | `"all"` | How recent the keywords' articles are: `all` (any time; Google's own mix, newest first), `1h`, `1d`, `7d`, `30d` or `1y` (the last hour, day, week, month, year). For hourly monitoring take `1h` on a schedule. |
| `maxArticles` | `integer` | `100` | Stop each keyword or topic at this many articles (0 = every article the feeds serve). Google's feed serves about 100 a keyword; past that the run reads one day at a time, newest day first, back to the time frame's start (`all`: until 60 empty days in a row). |
| `decodeUrls` | `boolean` | `false` | Resolve each article's Google News link to the publisher's own article URL (`url`; two more requests an article, so a run takes longer). Off: `url` stays empty and `google_news_url` leads to the article through Google. The price is the same. |
| `onlyNew` | `boolean` | `false` | Remember every article delivered under this memory (stateStoreName, or a name derived from the inputs) and skip it free in the next run: a scheduled task delivers only what is new. The input row counts the skipped (skipped_seen). |
| `stateStoreName` | `string` | `""` | The name of the onlyNew memory, so several tasks can share one or keep theirs apart. Empty: a name derived from the inputs. |
| `maxItems` | `integer` | `0` | Stop the run after this many article rows across every keyword and topic (0 = no limit). Input rows are free and not counted; a keyword or topic left unread at the cap gets a free `not_read` row. |

### Errors

**A run does not fail because of your input.** When an input cannot be used — a date that is not a date, an id in the wrong form, two settings that contradict each other — the run ends **Succeeded**, charges nothing, and says what to change:

- the status message starts with `INPUT REJECTED`;
- the dataset holds one row, `{"error": true, "code": "…", "message": "…"}`, and no results;
- the key-value store record `ERROR` holds the same object.

From code, check `error` on the first row before reading results.

A keyword with no article is not an error: it gets one free row with `status` = `no_results` (two exits agreed), and the run goes on with the others. A run that ends **Failed** is a fault on our side, never your input; it charges nothing, and we are alerted.

### FAQ

**Does it give the article's text, snippet or image?**

No. Google News' feeds carry the title, the publisher, the date and the link, not a snippet or an image, and the article's text is on the publisher's site. Turn on `decodeUrls` to get each publisher's article URL for your own crawl.

**Why is `url` empty?**

`url` (the publisher's own article URL) is filled when `decodeUrls` is on; `url_status` says `decoded`, `not_asked` (off) or `failed` (Google did not resolve that link; the row keeps its `google_news_url`, which still leads to the article).

**Which status is which?**

An input row's `status` is `ok` (articles served), `no_results` (Google lists no article for the keyword; two exits agreed), `not_found` (no such topic; two exits agreed), `invalid` (a value that is not a keyword, a section name or a news.google.com topic URL), `duplicate` (the same value again: read once), `failed` (a refusal or an error; free) or `not_read` (left at `maxItems`, the charge limit or the run's time limit). An article row's `status` is `ok`.

**Does it need a Google account or API key?**

No. Everything is read from Google News' public feeds, logged out.

### Integration

#### JavaScript

```javascript
import { ApifyClient } from 'apify-client';
const client = new ApifyClient({ token: 'YOUR_TOKEN' });
const run = await client.actor('hyperbach/google-news-scraper').call({"keywords": ["bitcoin"], "maxArticles": 50});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

#### Python

```python
from apify_client import ApifyClient
client = ApifyClient('YOUR_TOKEN')
run = client.actor('hyperbach/google-news-scraper').call(run_input={'keywords': ['bitcoin'], 'maxArticles': 50})
items = client.dataset(run['defaultDatasetId']).list_items().items
```

#### CLI

```bash
apify call hyperbach/google-news-scraper --input '{"keywords": ["bitcoin"], "maxArticles": 50}'
```

#### REST

```bash
curl -X POST "https://api.apify.com/v2/acts/hyperbach~google-news-scraper/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H 'Content-Type: application/json' -d '{"keywords": ["bitcoin"], "maxArticles": 50}'
```

#### AI agents and MCP

Apify's MCP server offers this Actor as a tool to Claude, Cursor, VS Code and any other MCP client. Connect `https://mcp.apify.com?tools=hyperbach/google-news-scraper` and ask, for example: "Get the 50 newest Google News articles about bitcoin". The agent fills the input from the table above and reads the rows from the run's dataset. The input names are the ones in the table above.

#### n8n, Make and Zapier

The Apify node in n8n, the Apify app in Make and the Apify integration in Zapier run this Actor on a schedule or from a trigger and read its dataset. A webhook on the run's end (Integrations on the Actor page) sends the rows on to your own endpoint. Nothing to install on our side.

### Support

**Disagree with a charge?** Write to apify@hyperbach.com with the run ID. We will ask Apify to compensate you, and the charge comes back to your Apify account as platform credit.

**Did it do the job?** A short [review on the Store](https://apify.com/hyperbach/google-news-scraper/reviews), at any rating, helps the next buyer choose.

### See also

- **[ChatGPT Scraper](https://apify.com/hyperbach/ai-search-answers)** — what ChatGPT, Gemini, Perplexity and Google's AI Mode and AI Overviews answer for your queries, with every source they cite.
- **[Substack Scraper](https://apify.com/hyperbach/substack-scraper)** — the posts of a Substack newsletter with the full text of free posts, the date, the paywall flag and the likes.
- **[Yahoo Finance Scraper](https://apify.com/hyperbach/yahoo-finance-scraper)** — Yahoo Finance quotes, statistics, company profiles and price history by ticker, for stocks, ETFs, indices, crypto and FX.

*This page is generated from the Actor's schemas and a live sample — it cannot describe a field the Actor does not have.*

# Actor input Schema

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

Search words, one search per line (`bitcoin`, `artificial intelligence`, `"electric vehicles" OR EV`). Google's own operators work: `site:reuters.com`, `OR`, `-word`, quotes, and `when:`, `after:YYYY-MM-DD`, `before:YYYY-MM-DD` for your own dates (then `timeframe` is not added to that line). Up to 1,000 keywords and topics a run. A line given twice gets a free `duplicate` row.

## `topics` (type: `array`):

Google News sections: `WORLD`, `NATION`, `BUSINESS`, `TECHNOLOGY`, `ENTERTAINMENT`, `SPORTS`, `SCIENCE`, `HEALTH`, `TOP_STORIES` (the front page), or a topic or section URL copied from news.google.com (`https://news.google.com/topics/…`, read in the URL's own region and language). A topic's feed is its own list (about 40-70 articles); `timeframe` does not apply to it.

## `regionLanguage` (type: `string`):

The Google News edition to read: country and language, as Google names it (`US:en` is the United States in English, `DE:de` Germany in German, `BR:pt-419` Brazil in Portuguese).

## `timeframe` (type: `string`):

How recent the keywords' articles are: `all` (any time; Google's own mix, newest first), `1h`, `1d`, `7d`, `30d` or `1y` (the last hour, day, week, month, year). For hourly monitoring take `1h` on a schedule.

## `maxArticles` (type: `integer`):

Stop each keyword or topic at this many articles (0 = every article the feeds serve). Google's feed serves about 100 a keyword; past that the run reads one day at a time, newest day first, back to the time frame's start (`all`: until 60 empty days in a row).

## `decodeUrls` (type: `boolean`):

Resolve each article's Google News link to the publisher's own article URL (`url`; two more requests an article, so a run takes longer). Off: `url` stays empty and `google_news_url` leads to the article through Google. The price is the same.

## `onlyNew` (type: `boolean`):

Remember every article delivered under this memory (stateStoreName, or a name derived from the inputs) and skip it free in the next run: a scheduled task delivers only what is new. The input row counts the skipped (skipped_seen).

## `stateStoreName` (type: `string`):

The name of the onlyNew memory, so several tasks can share one or keep theirs apart. Empty: a name derived from the inputs.

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

Stop the run after this many article rows across every keyword and topic (0 = no limit). Input rows are free and not counted; a keyword or topic left unread at the cap gets a free `not_read` row.

## Actor input object example

```json
{
  "keywords": [
    "bitcoin"
  ],
  "regionLanguage": "US:en",
  "timeframe": "all",
  "maxArticles": 50,
  "decodeUrls": false,
  "onlyNew": false,
  "stateStoreName": "",
  "maxItems": 100
}
```

# Actor output Schema

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

All scraped records in the default dataset. One row per article (and one free row per keyword or topic):

## `runSummary` (type: `string`):

How the run went: article rows charged, free rows, inputs by status, articles by URL status, the walk per keyword or topic (articles delivered, feeds and day windows read, articles met again or delivered by another input, the verdict), the source counters (calls, served, refused, exits, rotations, bytes) and the memory watch.

# 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 = {
    "keywords": [
        "bitcoin"
    ],
    "maxArticles": 50,
    "maxItems": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("hyperbach/google-news-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 = {
    "keywords": ["bitcoin"],
    "maxArticles": 50,
    "maxItems": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("hyperbach/google-news-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 '{
  "keywords": [
    "bitcoin"
  ],
  "maxArticles": 50,
  "maxItems": 100
}' |
apify call hyperbach/google-news-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,hyperbach/google-news-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/diX3D0Aha4hdOLGPl/builds/B5F4cOiv9qqVg9gUY/openapi.json
