# Google News Scraper (`alexmorain/google-news-scraper`) Actor

Scrape Google News by keyword, topic or location, past the 100-article cap: the Actor searches day by day and removes duplicates. Real publisher URLs decoded, optional full article text, new-only monitoring with webhook. Plain HTTP, no proxy.

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

## Pricing

from $0.40 / 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

This Actor turns [Google News](https://news.google.com/) into structured data. Give it search
queries, topics, locations or Google News URLs, and it returns every article: headline,
publisher, publication time, and the **real article URL on the publisher's site**, decoded
from Google's redirect link. Optionally it opens each article and adds the **full text**,
author and main image.

It reads Google News's own RSS feeds over plain HTTP. No browser, no login, no proxy to pay
for. 1,300 articles take about a minute. Pricing is pay per event: **$1.00 per 1,000
articles** at the entry price, **from $0.40 / 1,000 on Gold**, URL decoding included; $2.50
per 1,000 articles with full text ($1.20 on Gold); and $0.002 per run.

Google News has no public API. This Actor is the closest thing to a Google News API: a
query in, JSON out, scheduled or called from your code.

***

### What does Google News Scraper do?

Google shows at most **100 articles per search**, whatever period you ask for. Wider periods
do not help: Google picks a sample. On a 7-day search for `mistral ai`, Google's own
`when:7d` filter returns 54 articles and a 7-day date range returns 49. Searched one day at
a time, the same week holds 220.

So when you set a time range of 2 days or more, the Actor runs **one search per day**,
newest day first, and merges them. Neighbouring days overlap in Google's results (its days
end at midnight Pacific time, not UTC), so 10% to 25% of the raw rows are duplicates. The
Actor removes them before pushing, and you are charged once per article.

Measured on 18 October 2026, US and French editions, 11 to 17 October:

| Query | Edition | `when:7d` | One 7-day search | This Actor, day by day |
|---|---|---|---|---|
| `mistral ai` | US:en | 54 | 49 | **220** |
| `nvidia` | US:en | 100 | 100 | **676** |
| `airbus` | US:en | 100 | 100 | **583** |
| `renault` | FR:fr | 100 | 100 | **570** |

The raw day-by-day feeds held 242, 800, 641 and 645 rows for these four: those extra rows
are the overlap duplicates you are not charged for.

### Why use this Google News scraper?

- **Brand and media monitoring.** Schedule it hourly or daily with **New articles only**:
  each run returns only articles never returned before, and a webhook pings Slack, Discord or
  your own endpoint when something new comes out. A quiet run costs $0.002.
- **PR and competitor tracking.** Every outlet that covered a launch, with the publisher URL
  ready to open, sort by domain or send to a spreadsheet.
- **Datasets for analysis and AI.** Months of coverage on a topic, with full text, for
  sentiment analysis, summaries or a RAG index.
- **Sales signals.** Funding rounds, hires and expansions of the companies you prospect,
  using Google's operators: `"Example Company" (raises OR funding OR hires)`.

What you get that other Google News scrapers miss:

- **Real publisher URLs.** Google's RSS links point to `news.google.com/rss/articles/…`. The
  Actor decodes each one to the publisher's address. Rows where decoding fails keep the
  Google link and are **not charged**.
- **Every article of each story.** Topics, top stories and location feeds group several
  outlets under one story, and only the lead article is a feed item. On the US top stories,
  38 items hide 180 articles. With **Include all articles of each story** on (the default),
  each becomes its own row, linked by `storyId` and `storyRank`.
- **No silent fallback to US news.** Google answers an edition code it does not know (say
  `UK:en` instead of `GB:en`) with the US edition, without an error. The Actor checks every
  edition and skips an unknown one with a warning.
- **It tells you what it could not get.** When one day still holds more than 100 articles
  for a broad query, the run's status message says which query and how many days, so you
  know to narrow it.

### What data can I extract from Google News?

| Field | Description |
|---|---|
| `title` | Headline, without the trailing " - Publisher" |
| `url` | Article URL on the publisher's site, decoded |
| `source`, `sourceDomain` | Publisher name and domain |
| `publishedAt` | Publication time, ISO 8601 UTC |
| `input`, `inputType`, `edition` | The query, topic, location or URL that found it, and the edition |
| `storyId`, `storyRank`, `storyPublishedAt` | Story grouping for topic, top stories and location feeds |
| `text`, `textLength`, `author`, `image`, `summary` | With Fetch article text on |
| `textStatus` | `ok`, `blocked` (paywall or bot protection), `not-found`, `no-article-text`, `error`, `not-decoded`, `not-requested` |
| `googleNewsUrl`, `articleId` | Google's link and ID for the article |

### How to scrape Google News

1. Type one or more **search queries**. Google's operators work: `"exact phrase"`, `OR`,
   `-exclude`, `site:reuters.com`, `intitle:`.
2. Pick a **time range** (`7d`, `1m`, `1y`) or a fixed period with **From date** and
   **To date**. Without either, Google returns its default ranking, at most 100 articles.
3. Choose one or more **editions** (`US:en`, `GB:en`, `FR:fr`, `DE:de`, `IN:en`, `BR:pt-419`…).
4. Set **Max articles per query**, or `0` for every article of the period.
5. Press **Start**, then download the dataset as JSON, CSV, Excel or HTML.

Topics (business, technology, sports…), locations (`Paris`, `Texas`) and pasted Google News
URLs (a search or topic page from your browser) work the same way and can be combined
with queries in one run.

### How much does it cost to scrape Google News?

| Event | Free | Bronze | Silver | Gold and up |
|---|---|---|---|---|
| Article, publisher URL decoded | $1.00 / 1,000 | $0.80 / 1,000 | $0.60 / 1,000 | $0.40 / 1,000 |
| Full-text article (instead of Article) | $2.50 / 1,000 | $2.00 / 1,000 | $1.60 / 1,000 | $1.20 / 1,000 |
| Run start | $0.002 | $0.002 | $0.002 | $0.002 |

A week of news on one busy company (about 600 articles) costs $0.60 on the Free plan, $0.24
on Gold. Duplicates, rows without a decoded URL, and articles already returned in New
articles only mode are free. The log announces the maximum cost of the run at its start,
and the Actor stops cleanly at the maximum charge you set in the run options.

Full text is charged only when it comes out. Paywalled and bot-protected sites return the
article without text at the plain article price: in our tests from Apify's servers, 78% of
articles came with text (about 70% in English, more in French).

### Input

See the **Input** tab for every option. The ones worth knowing:

- **Time range** counts back from now. Up to 47 hours it uses Google's `when:` filter (one
  search, at most 100 articles). From `2d` on, it searches day by day.
- **From date / To date** are UTC days. They take precedence over Time range.
- **Editions** multiply the searches: 3 queries in 2 editions are 6 searches, each with its
  own Max articles.
- **Mode: New articles only** keeps a registry in your Apify account, matched on Google's ID
  and on the publisher URL, so an article republished under a new Google link is still
  recognised. **Registry key** lets you keep one registry while you edit the query list.
- **Webhook URL** receives a JSON summary (`runId`, `datasetId`, `items`, `feeds`) when a
  run returns at least one article.

Example, daily monitoring of two brands in English and French:

```json
{
    "queries": ["\"Example Company\"", "\"Example Brand\" -recipe"],
    "editions": ["US:en", "GB:en", "FR:fr"],
    "timeRange": "2d",
    "maxArticles": 0,
    "mode": "new-only",
    "webhookUrl": "https://hooks.slack.com/services/T000/B000/XXXX"
}
```

### Output

You can download the dataset in various formats such as JSON, HTML, CSV, or Excel.

```json
[
    {
        "title": "Example Company unveils its new electric model",
        "url": "https://www.example-news.com/business/2026/10/17/example-company-electric-model",
        "source": "Example News",
        "sourceDomain": "example-news.com",
        "publishedAt": "2026-10-17T09:30:00Z",
        "googleNewsUrl": "https://news.google.com/rss/articles/CBMiXEFVX3lxTE5leGFtcGxl?oc=5",
        "articleId": "CBMiXEFVX3lxTE5leGFtcGxl",
        "storyId": null,
        "storyRank": null,
        "storyPublishedAt": null,
        "input": "\"Example Company\"",
        "inputType": "query",
        "edition": "US:en",
        "textStatus": "ok",
        "text": "Example Company presented its new electric model on Friday...",
        "textLength": 3200,
        "author": "Jane Example",
        "image": "https://www.example-news.com/images/example-model.jpg",
        "summary": "Example Company's new model goes on sale next spring.",
        "scrapedAt": "2026-10-17T10:00:00Z"
    },
    {
        "title": "Markets close higher as tech shares rally",
        "url": "https://www.example-wire.com/markets/stocks-close-higher",
        "source": "Example Wire",
        "sourceDomain": "example-wire.com",
        "publishedAt": null,
        "storyId": "CBMiYUFVX3lxTE9leGFtcGxl",
        "storyRank": 2,
        "storyPublishedAt": "2026-10-17T21:05:00Z",
        "input": "BUSINESS",
        "inputType": "topic",
        "edition": "US:en",
        "textStatus": "not-requested",
        "text": null
    }
]
```

### Tips

- **Monitoring:** schedule the same input with `timeRange` a little longer than the
  schedule interval (`2d` for a daily run, `3h` for an hourly one) and **New articles only**.
  The overlap catches late-indexed articles, the registry makes sure you pay for each once.
- **Broad queries:** if the status message reports days still at 100 articles, split the
  query (`nvidia earnings`, `nvidia chips`…), add editions, or narrow it with `site:` or
  `intitle:`. Google exposes no finer slice than a day.
- **Full text at scale:** keep the default 1 GB of memory. Text extraction is the slow part,
  about 2 articles per second.
- **From code:** call the Actor through the [Apify API](https://docs.apify.com/api/v2) or
  the Python and JavaScript clients:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("alexmorain/google-news-scraper").call(run_input={
    "queries": ["Example Company"],
    "timeRange": "7d",
    "maxArticles": 0,
})
for article in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(article["publishedAt"], article["source"], article["url"])
```

### FAQ

#### Is there a Google News API?

No public one. Google News exposes RSS feeds for searches, topics and locations, capped at
about 100 items and with links that redirect through Google. This Actor reads those feeds,
goes past the cap day by day and decodes the links: it is the practical Google News API.

#### How do I get more than 100 results from Google News?

Set a time range of 2 days or more, or From and To dates, and Max articles to `0`. The Actor
runs one search per day of the period and merges them without duplicates.

#### Why does an article have no publisher URL?

Google could not resolve that link at the time of the run. The row keeps `googleNewsUrl`,
which still opens the article in a browser, and it is not charged. If a whole run has none,
Google has probably changed its link format: open an issue.

#### Why is `publishedAt` empty on some rows?

Those rows come from a story cluster in a topic, top stories or location feed. Google gives
a time for the story's lead article only: it is in `storyPublishedAt`.

#### Can I scrape a single publisher?

Yes: add `site:example.com` to a query, for example `site:reuters.com tesla`, or
`site:example.com` alone with a time range to list everything Google indexed from it.

#### Is it legal to scrape Google News?

Our Actors are ethical and do not extract any private user data, such as email addresses,
gender, or location. They only extract what the user has chosen to share publicly. We
therefore believe that our Actors, when used for ethical purposes by Apify users, are safe.
However, you should be aware that your results could contain personal data. Personal data
is protected by the GDPR in the European Union and by other regulations around the world.
You should not scrape personal data unless you have a legitimate reason to do so. If you're
unsure whether your reason is legitimate, consult your lawyers. Article texts belong to
their publishers: use them for analysis, not republication.

### Support

Something wrong or missing? Open an issue in the **Issues** tab, it gets answered and fixed.
If the Actor saved you time, a short review helps others find it. This Actor is not
affiliated with or endorsed by Google.

# Actor input Schema

## `queries` (type: `array`):

What you would type in the Google News search bar, one per line. Google's operators work: <code>"exact phrase"</code>, <code>OR</code>, <code>-exclude</code>, <code>site:lemonde.fr</code>, <code>intitle:</code>.<br><br>Each query runs in each edition below. An article found by two queries is returned and charged once, under the first query.

## `timeRange` (type: `string`):

How far back to look, counted from now: <code>1h</code>, <code>12h</code>, <code>1d</code>, <code>7d</code>, <code>2w</code>, <code>3m</code>, <code>1y</code>.<br><br>Up to 47 hours, Google's own <code>when:</code> filter is used (one search, at most 100 articles). From 2 days on, the Actor searches each day separately to go past the 100-article cap. Leave empty and set dates below for a fixed period, or leave both empty for Google's default ranking (at most 100 articles, any age).

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

First day to include, <code>YYYY-MM-DD</code>, in UTC. The Actor searches every day from here to <b>To date</b> (today if empty). Takes precedence over Time range.

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

Last day to include, <code>YYYY-MM-DD</code>, in UTC. Alone, it reads the 30 days up to that date.

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

Stop each query, topic or location after this many articles, <b>per edition</b>. The newest articles come first. Set <code>0</code> for no cap: every article of the period.

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

Google News edition codes, <code>COUNTRY:language</code>. Examples: <code>US:en</code>, <code>GB:en</code>, <code>IN:en</code>, <code>AU:en</code>, <code>CA:fr</code>, <code>FR:fr</code>, <code>DE:de</code>, <code>ES:es</code>, <code>IT:it</code>, <code>NL:nl</code>, <code>BR:pt-419</code>, <code>MX:es-419</code>, <code>JP:ja</code>, <code>IN:hi</code>. Empty means <code>US:en</code>.<br><br>Google silently serves US news for a code it does not know. The Actor checks every code and skips an unknown one with a warning instead of returning the wrong country.

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

Google News sections for each edition: top stories, world, business, technology and so on. A section lists only its latest articles, up to about 70 stories, and dates only filter what it lists.

## `locations` (type: `array`):

Local news for a city, region or country, as Google News names it: <code>Paris</code>, <code>Texas</code>, <code>Munich</code>.

## `googleNewsUrls` (type: `array`):

Pages copied from your browser on news.google.com: a search, a topic (<code>/topics/…</code>), a section or a location. The edition in the URL is kept. Full-coverage story pages and publisher pages are not available as feeds.

## `fetchArticleText` (type: `boolean`):

Open each article on the publisher's site and add its full text, author, main image and summary. Charged as <b>Article with text</b> instead of Article, only when the text comes out: paywalled and bot-protected sites (a quarter of English articles in our tests, fewer in other languages) return the article without text, at the plain article price. Slower: one more page per article.

## `expandStoryClusters` (type: `boolean`):

Topics, top stories and locations group several outlets' articles under one story, and only the first is a feed item. On the US top stories, that hides 4 articles out of 5. On, every article of each story becomes its own row, with <code>storyId</code> and <code>storyRank</code> linking it to the story (these rows have no own date, see <code>storyPublishedAt</code>). Search results are not grouped.

## `mode` (type: `string`):

<b>All articles</b> returns every article found, on every run.<br><br><b>New articles only</b> keeps a persistent registry of what previous runs returned and charged, and returns only articles never returned before, matched on Google's ID and on the publisher URL. Schedule it hourly or daily with a short time range for brand and media monitoring: a quiet run costs the start fee only.

## `registryKey` (type: `string`):

By default the registry is tied to the exact queries, topics, locations and editions, so changing any of them starts a fresh one. Set your own key to keep one registry while you edit the list.

## `webhookUrl` (type: `string`):

If set, the Actor POSTs a small JSON summary to this URL at the end of the run, <b>only when at least one article was returned</b>: <code>actor</code>, <code>runId</code>, <code>datasetId</code>, <code>mode</code>, <code>items</code>, <code>feeds</code>. With New articles only and a schedule, that is a push notification when your brand is in the news.<br><br>Use the final URL: a redirect is not followed, except a 307 or 308, which gets the same POST once. An unreachable webhook is logged as a warning and never fails the run. Stored encrypted, since a webhook URL often carries its own access token.

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

Leave as is. Google News answers the Actor without a proxy (no refusal in 2,800 test requests), so none is used and none is paid. If Google ever refuses, the Actor switches to Apify datacenter proxies by itself. A proxy chosen here is used for Google and for publisher pages.

## Actor input object example

```json
{
  "queries": [
    "OpenAI"
  ],
  "timeRange": "7d",
  "maxArticles": 150,
  "editions": [
    "US:en"
  ],
  "fetchArticleText": false,
  "expandStoryClusters": true,
  "mode": "all",
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

Dataset of the articles found

# 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 = {
    "queries": [
        "OpenAI"
    ],
    "timeRange": "7d",
    "maxArticles": 150,
    "editions": [
        "US:en"
    ],
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("alexmorain/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 = {
    "queries": ["OpenAI"],
    "timeRange": "7d",
    "maxArticles": 150,
    "editions": ["US:en"],
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("alexmorain/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 '{
  "queries": [
    "OpenAI"
  ],
  "timeRange": "7d",
  "maxArticles": 150,
  "editions": [
    "US:en"
  ],
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call alexmorain/google-news-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,alexmorain/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/55avlflHXI25x2P4P/builds/4jLBenPbi6eM5FlhG/openapi.json
