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

Search Google News in any language and country and get the real publisher URL, not Google's redirect link. Returns headline, source name, publish time, description and both URLs. Supports time windows of the last hour, day or week. Up to 100 articles per query, which is Google's own cap.

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

## Pricing

from $1.75 / 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.

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

## Google News Scraper

Scrapes Google News RSS feeds — search terms, topic sections and top stories —
and, unlike most scrapers in this category, gives you **the publisher's real
article URL**, not Google's redirect link.

### The redirect problem, and what this actor actually does about it

Every link in a Google News feed looks like this:

```
https://news.google.com/rss/articles/CBMilgFBVV95cUxQTU9VbHZPQ2czTUlfNVZMVk53...?oc=5
```

That is not the article. It is a Google redirect, and it is the single most
common complaint about scrapers in this category: they hand you that string and
call it the article URL.

Two things were measured on 2026-08-24 and are worth stating plainly:

- **The identifier does not decode to a URL.** In feeds published before 2024,
  the `CBMi...` segment was base64 of a tiny protobuf whose only string was the
  destination, and decoding it was enough. Current feeds carry an opaque
  `AU_yqL...` token instead. This actor still decodes the old format when it
  meets one, because it is free — but on live feeds today it never fires.
- **Following redirects does not work either.** The link 302s to a Google News
  interstitial that performs the real navigation from JavaScript. A plain HTTP
  client sees a 592 KB app shell whose canonical URL points back at
  news.google.com.

What does work, with no browser and no headless Chrome: fetch the interstitial,
read the per-article signature it embeds, and post it to Google News's own
`batchexecute` endpoint — the same request the page's own JavaScript makes. In
testing this resolved **25 out of 25** articles.

So the output carries **both** fields, and they are never confused:

| field | what it is |
|---|---|
| `google_news_url` | Google's redirect link, always present |
| `resolved_url` | the publisher's own URL, or `null` |

`resolved_url` is `null` when — and only when — resolution genuinely failed
(Google refused the interstitial, or the signature endpoint changed). It is
never quietly filled with the redirect URL. Set `resolveUrls` to `false` if you
do not need it: resolution costs one extra page fetch per article, so turning it
off makes runs noticeably faster and cheaper.

### Limits you should know before paying for a run

- **Google caps a search feed at about 100 articles per query, and there is no
  pagination.** Measured on 2026-08-24: a search feed returned 100 items, a
  topic feed 70, and the top-stories feed 38. No parameter moves those numbers.
  To go past 100 you need more queries — narrower terms, or the same term split
  across `timeRange` windows — not a bigger `maxItems`.
- **`timeRange` applies to search queries only.** Google implements it by
  appending a `when:` token to the query text, so `topic:` and `top` feeds
  ignore it.
- **The feed is a headline feed, not an article feed.** See the next section.

### Output fields

| field | notes |
|---|---|
| `guid` | Google's stable article identifier; runs are de-duplicated on it |
| `title` | headline, with the source name appended by Google |
| `google_news_url` | the redirect link, always present |
| `resolved_url` | publisher URL, or `null` — see above |
| `published_at` | RFC 822 timestamp exactly as the feed gives it |
| `source_name` | publication name, e.g. `The Guardian` |
| `source_url` | publication homepage, e.g. `https://www.theguardian.com` |
| `description_html` | Google's snippet markup |
| `description_text` | the same snippet with tags stripped |
| `query` | which input entry produced this article |
| `language`, `country` | the edition that was read |

**What the source does not give, and is therefore not invented here:** article
body text, author, image, word count, sentiment, and any engagement or share
count. Google News RSS carries none of them. `description` is an anchor tag plus
the source name — a link, not a summary — so `description_text` is short by
nature. Anything absent is `null`, never `0` or `""`, because a zero reads as a
measurement.

### Input

- `queries` — mix freely: `openai` (search), `topic:TECHNOLOGY` (section), `top`
  (top stories). Topics are `WORLD`, `NATION`, `BUSINESS`, `TECHNOLOGY`,
  `ENTERTAINMENT`, `SPORTS`, `SCIENCE`, `HEALTH`.
- `language` / `country` — Google's `hl` and `gl`. The `ceid` parameter is built
  from both automatically (`hl=en-US` + `gl=US` gives `ceid=US:en`).
- `timeRange` — `1h`, `1d`, `7d` or `1y`, search queries only.
- `maxItems` — total across all queries.
- `resolveUrls` — on by default.
- `proxyConfiguration` — recommended. Google rate-limits per address, and the
  actor rotates its exit address between queries and on every retry.

### Reliability

Refusals (HTTP 403, 429, 5xx, and Google's unusual-traffic page) are treated as
transient and retried from a fresh proxy address. A malformed feed, an unknown
topic section, or a query that simply matched nothing is treated as permanent
and is not retried — retrying those would spend your money to learn the same
answer four times. A query that returns nothing is reported in the log and is
**not** charged for.

# Actor input Schema

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

One entry per feed to scrape. A plain search term such as `openai` runs a Google News search. `topic:TECHNOLOGY` reads a topic section (WORLD, NATION, BUSINESS, TECHNOLOGY, ENTERTAINMENT, SPORTS, SCIENCE, HEALTH). `top` reads the top-stories feed. The three forms can be mixed in one run.

## `language` (type: `string`):

Google's `hl` parameter, for example `en-US`, `de` or `pt-BR`. It selects the edition's language and is combined with the country into Google's `ceid` parameter automatically.

## `country` (type: `string`):

Google's `gl` parameter as a two-letter country code, for example `US`, `DE` or `TH`. Decides which national edition of Google News is read.

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

Restrict search results to the last hour, day, week or year. Google applies this by appending a `when:` token to the query, so it affects search queries only and is ignored for `topic:` and `top` feeds.

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

Stop after this many articles across all queries. Google itself caps a search feed at about 100 articles per query and offers no pagination, so asking for more than 100 requires more than one query.

## `resolveUrls` (type: `boolean`):

Recover each publisher's real article URL from Google's redirect link and put it in `resolved_url`. This costs one extra page fetch per article, so switching it off makes runs faster and cheaper at the price of leaving `resolved_url` empty.

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

Recommended. Google rate-limits repeated requests from one address, and a rotating proxy is what clears it.

## Actor input object example

```json
{
  "queries": [
    "openai"
  ],
  "language": "en-US",
  "country": "US",
  "maxItems": 100,
  "resolveUrls": true,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `articles` (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 = {
    "queries": [
        "openai"
    ],
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("superslowsloth/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"],
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("superslowsloth/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"
  ],
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call superslowsloth/google-news-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,superslowsloth/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/u0kibcFlf0uFGZJHo/builds/9CGHHusgqoD8HokFJ/openapi.json
