# Google News Scraper: Real Article URLs (No Login) (`kizukidata/google-news-feed`) Actor

Scrape Google News by keyword or topic: one row per article with title, outlet, publication time, publisher's article URL and News link. Use it for news and brand monitoring. The Only new articles option returns only articles added since your last run. No article text. Not affiliated with Google.

- **URL**: https://apify.com/kizukidata/google-news-feed.md
- **Developed by:** [Kizuki](https://apify.com/kizukidata) (community)
- **Categories:** News, Marketing, Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.10 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

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: Real Article URLs (No Login)

**Google News Scraper** returns **recent Google News results for your search queries and topic sections** as **JSON, CSV or Excel**. Give it up to 10 queries or topics (Top stories, Business, Technology, …), an edition (country and language) and a period, and get back for each article the **title**, the **outlet** and its site, **the outlet's own article URL** (`articleUrl`) so a row links straight to the publisher instead of to Google, the **publication time** and the article's Google News link. For topic sections it also returns **other outlets' coverage of the same story**, as Google News groups it.

It needs **no login and no API key**, and it does not open the publishers' pages. The same article found by two queries is returned **once**, articles left out by a filter are **not charged**, and a scheduled run can return **only the articles it has not returned before**.

This Actor is an independent tool. It is **not affiliated with, endorsed by or sponsored by Google**. Try it with an empty input: it returns a small sample (20 articles about "artificial intelligence" from the last 24 hours, US English edition).

### Use cases

- **Brand and competitor monitoring.** One query per brand, an hourly or daily schedule, and only the articles that appeared since the last run.
- **Topic briefings.** A daily pull of `BUSINESS` and `TECHNOLOGY` with the other outlets' coverage of each story, ready for a digest.
- **Media analysis.** Outlet mix, publication times and how widely a story was covered, as a table.
- **Research and datasets.** A news corpus for a period and an edition, de-duplicated across queries.
- **Agent and MCP use.** A short query with `maxItems` returns headlines, outlets and article URLs for an assistant to cite.

### What data can you get?

| Field | Description |
|---|---|
| `id` | Stable article ID (hash of the feed's article ID); used for de-duplication |
| `source` | `Google News` |
| `query` | Your query that found the article (the first one, when several did); `null` for topic rows |
| `topic` | The topic section that listed the article, for example `TECHNOLOGY`; `null` for query rows |
| `edition` | The edition searched, for example `US:en` |
| `title` | Article title, without the " - outlet" suffix |
| `outlet` | Outlet name, for example `Reuters` |
| `outletUrl` | Outlet's site, for example `https://www.reuters.com` |
| `publishedAt` | Publication time, ISO 8601 (UTC) |
| `articleUrl` | The outlet's own article URL, for example `https://www.reuters.com/world/...`; `null` when it could not be resolved |
| `articleUrlReason` | Fixed reason when `articleUrl` is `null` (not resolved, or not checked because `resolveArticleUrls` is off); `null` when the URL is there |
| `googleNewsUrl` | The article's Google News link |
| `relatedCoverage` | Topic rows: other outlets' coverage of the same story (`title`, `outlet`), as Google News lists it (usually up to 4); empty for query rows |
| `isNew` | With **Only new articles**: `true`; otherwise `null` |
| `scrapedAt` | When this run read the feed |

Every row has every field; a value the feed does not provide is `null`. **Article text and author names are not returned.**

**The outlet's own article URL is returned for every row by default** (`resolveArticleUrls: true`): the run returns one row per article with `articleUrl` filled in, which is why it takes a little longer than a run that returns the Google News link alone. A link that cannot be resolved does not lose its row: `articleUrl` is `null` and `articleUrlReason` says why. Set `resolveArticleUrls: false` to get the Google News link only.

### How to use Google News Scraper

1. Enter one or more **Search queries** (`queries`), or pick **Topics** (`topics`), or both.
2. Optionally pick the **Edition** (`edition`) and the **Period** (`timespan`), and narrow with **Published after** (`publishedAfter`), **Only these outlets** (`includeOutlets`) or **Exclude outlets** (`excludeOutlets`).
3. Set **Maximum results** (`maxItems`) and run the Actor. **Resolve the outlet article URL** (`resolveArticleUrls`) is on by default; turn it off for a faster run that returns only the Google News link.
4. Download the dataset as JSON, CSV or Excel, or read it through the API.

#### Queries

Queries use the Google News search syntax:

- **Exact phrases** go in double quotes: `"interest rates"`.
- **OR** between terms: `tesla OR byd OR rivian`.
- A **minus sign** excludes a word: `apple -fruit`.
- `site:` keeps one outlet: `chip exports site:reuters.com`.
- The period is added as `when:24h` (from `timespan`). A query with its own `when:` keeps it.

#### Topics

`topics` reads the edition's topic sections, one request each: `TOP` (top stories), `WORLD`, `NATION` (the edition's country), `BUSINESS`, `TECHNOLOGY`, `ENTERTAINMENT`, `SPORTS`, `SCIENCE`, `HEALTH`. A topic section lists the latest stories (Period does not apply; use `publishedAfter`), and each row carries `relatedCoverage`: the other outlets Google News groups under the same story, a quick signal of how widely a story is covered. When `topics` is set and `queries` is left at its default, only the topics are read.

#### Filters

- `publishedAfter`: keep articles published at or after an ISO 8601 date or date-time (UTC when no zone is given). For hourly schedules, set it to the previous run's start.
- `includeOutlets` / `excludeOutlets`: outlet domains (a domain also matches its subdomains: `reuters.com` matches `uk.reuters.com`) or exact outlet names, up to 50 each.
- Articles left out by a filter are **not written and not charged**.

#### Split by day (more than 100 articles per query)

`splitByDay: true` searches each query **one day at a time** (Google News' `after:` / `before:` operators), newest day first, so a query can return more than the feed's 100 articles per request. It is **off by default**.

- At most **7 one-day windows per run** in total: the number of days is the Period in days (hours count as one day), divided among the queries (for example 7 days for one query, 3 days each for two). Up to 7 queries.
- Windows are requested one at a time, 2 seconds apart. Neighbouring windows overlap by a day; an article found twice is returned and charged once.
- A query with its own `when:`, `after:` or `before:` is not split.

#### Editions

`US:en`, `GB:en`, `CA:en`, `AU:en`, `IN:en`, `JP:ja`, `DE:de`, `FR:fr`, `ES:es`, `IT:it`, `BR:pt-419`, `MX:es-419`, `KR:ko`, `TW:zh-Hant`, `NL:nl`. The edition decides which outlets and which language Google News favours.

#### Input example

```json
{
    "queries": ["electric vehicles", "\"interest rates\""],
    "timespan": "7d",
    "edition": "GB:en",
    "maxItems": 50
}
```

### Input

| Field | Default | What it does |
|---|---|---|
| `queries` | `["artificial intelligence"]` | Search queries (up to 10) |
| `topics` | `[]` | Topic sections: `TOP`, `WORLD`, `NATION`, `BUSINESS`, `TECHNOLOGY`, `ENTERTAINMENT`, `SPORTS`, `SCIENCE`, `HEALTH` |
| `timespan` | `24h` | Period for queries: 1 to 48 hours or 1 to 30 days; does not apply to topics |
| `edition` | `US:en` | Country and language edition |
| `publishedAfter` | empty | Keep articles published at or after an ISO 8601 date or date-time |
| `includeOutlets` | `[]` | Only these outlet domains or exact names (up to 50) |
| `excludeOutlets` | `[]` | Drop these outlet domains or exact names (up to 50) |
| `splitByDay` | `false` | Search each query one day at a time, for more than 100 articles per query |
| `onlyNewItems` | `false` | Return only articles that earlier runs have not returned |
| `maxItems` | `20` | Maximum rows per run, across all queries (1 to 1,000) |
| `resolveArticleUrls` | `true` | Look up the outlet's own article URL for every returned row |
| `proxyConfiguration` | direct connection | Proxy settings (country, groups, custom proxy URLs) |

### Output

One row per article, every field present. Values below are illustrative.

#### Output example

```json
{
    "id": "8d1f2a6c0b9e4f37",
    "source": "Google News",
    "query": "electric vehicles",
    "topic": null,
    "edition": "GB:en",
    "title": "EV sales rise for the third month in a row",
    "outlet": "Example News",
    "outletUrl": "https://www.example-news.com",
    "publishedAt": "2026-11-04T09:15:00.000Z",
    "googleNewsUrl": "https://news.google.com/rss/articles/CBMi...?oc=5",
    "articleUrl": "https://www.example-news.com/2026/11/04/ev-sales-rise",
    "articleUrlReason": null,
    "relatedCoverage": [],
    "isNew": null,
    "scrapedAt": "2026-11-04T10:00:00.000Z"
}
```

### New articles only

Run the same input on a schedule and get only what is new:

- **Only new articles** (`onlyNewItems: true`): returns only articles that no earlier run with the **same queries and edition** returned. Each returned row has `isNew: true`. When nothing is new, the run ends successfully with an empty dataset and the status message `No new items since the previous run (…).`
- The Actor remembers what it returned in a **named key-value store in your Apify account** (`state-google-news-…`), one record per query, keyed by a hash of the queries and the edition. Changing those starts a new history; changing `timespan` or `maxItems` does not.
- An article counts as returned only after it was written to the dataset. Articles left out by `maxItems` or by your maximum cost come back as new on the next run.
- Articles not seen for **90 days** are forgotten (they would count as new again).
- **Do not run the same input twice at the same time**: both runs read the same history, so both return (and charge) the same new articles.
- Runs paid for with a temporary account may not keep their history beyond that account's lifetime.

### How much does it cost?

Google News Scraper uses **pay-per-event** pricing: you pay for the articles it returns, not for the time it runs. At the Free tier 1,000 articles cost $1.70; at Gold, $1.10.

| Apify plan (discount tier) | Price per 1,000 articles | Price per article |
|---|---|---|
| **Free** | $1.70 | $0.0017 |
| **Starter (Bronze)** | $1.50 | $0.0015 |
| **Scale (Silver)** | $1.30 | $0.0013 |
| **Business (Gold)** | $1.10 | $0.0011 |

Apify's Free plan includes USD 5 of monthly usage, which covers about 2,941 articles at the Free tier price,
run start fees aside.

- **Run start fee**: the platform default per run (see the Pricing tab).
- Articles dropped as duplicates across queries or by the timespan filter are **not charged**.
- Resolving the publisher URL is included in the article price; it is not a second charge.
- With `onlyNewItems`, articles returned by earlier runs are **not charged** again.
- **Maximum results** (`maxItems`) caps the total rows written.

### Use with AI agents (MCP)

Google News Scraper works as a tool for AI agents such as Claude, Cursor and n8n agents through the Apify MCP server. Load only this Actor with this server URL:

```text
https://mcp.apify.com?tools=kizukidata/google-news-feed
```

- **Claude Code**: run `claude mcp add apify "https://mcp.apify.com?tools=kizukidata/google-news-feed" -t http`.
- **Claude (web or desktop app)**: open **Customize → Connectors**, choose **Add custom connector**, name it `Apify` and paste the server URL above.
- **Cursor**: add the server to `~/.cursor/mcp.json` (or `.cursor/mcp.json` in a project):

```json
{
    "mcpServers": {
        "apify": { "url": "https://mcp.apify.com?tools=kizukidata/google-news-feed" }
    }
}
```

- **n8n**: add the Apify node (on self-hosted n8n, install the community package `@apify/n8n-nodes-apify`) and choose **Run an Actor and get dataset**; for an n8n AI Agent, add **Apify Tool** as a tool.

The server signs you in to Apify with OAuth. A client that cannot use OAuth can send your Apify API token in an `Authorization: Bearer <APIFY_TOKEN>` header instead.

#### What to send from an agent

Calling it with **no arguments** (`{}`) runs the small default sample. Pass `queries` (or `topics`) and `maxItems`; add `edition`, `timespan` or `publishedAfter` to narrow the results. The dataset has a **compact view** (`publishedAt`, `title`, `outlet`, `articleUrl`) for short answers. `maxItems` also bounds how many articles the run resolves a publisher URL for. When a run returns nothing, the dataset stays empty and the run's status message says why, and also names input fields it did not recognise, such as a mistyped key.

### Integrations and API

Run the Actor from your own code or from an automation tool. Replace `<APIFY_TOKEN>` with your API token.

#### n8n, Make and Zapier

Use the Apify integration, choose **Run Actor**, and pass `queries` with `onlyNewItems: true`. Add **Get dataset items** and map `title`, `outlet`, `publishedAt` and `articleUrl` to a Slack message, a sheet, a digest or a model step. A daily schedule is usually enough for a news monitor; hourly works for a fast-moving topic.

#### cURL

```bash
curl -X POST "https://api.apify.com/v2/acts/kizukidata~google-news-feed/runs" \
  -H "Authorization: Bearer <APIFY_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"queries":["electric vehicles"],"edition":"GB:en","timespan":"7d","maxItems":50}'
```

Poll `GET https://api.apify.com/v2/actor-runs/<RUN_ID>` for the status, read `defaultDatasetId`, then fetch `GET https://api.apify.com/v2/datasets/<DATASET_ID>/items?format=json`.

### Limitations

- **No article text, no author names, no images.** `articleUrl` is the article's address, not its content: the Actor does not open the outlet's page.
- `articleUrl` is looked up through Google News, so a publisher that Google links to in an unusual way, a lookup that Google refuses, or a lookup that runs out of time leaves that row's `articleUrl` empty (`articleUrlReason` says which).
- Titles are as Google News lists them, in the edition's language mix. The Actor does not translate them.
- The feed decides which articles it lists and in which order; it is not a complete archive of everything published, and it is **by relevance, not strictly by date**. Sort by `publishedAt` when you need the newest first.
- **One request per query or topic** (or per day with `splitByDay`). The feed lists at most **100 articles per request**, so a run returns at most 100 × the number of requests.
- Each query gets a **fair share** of `maxItems`; a query with fewer articles passes the rest on to the queries after it.
- **Maximum results** (`maxItems`, default 20) caps each run, across all queries. Runs started by AI agents usually have no spending limit, so this is the main cost control.
- **If Google News answers "too many requests" or shows a consent page, the run stops at once**: the queries, topics or days not read yet are listed in OUTPUT `uncheckedInputs`, and the articles already read are kept. A query with no matching articles ends successfully with an empty dataset and says so; a run fails only when it could not return any article because of a problem on our side or the feed's.
- `relatedCoverage` lists what Google News groups under a story in topic feeds (titles and outlets only); search results carry none.
- `splitByDay` relies on Google News' `after:` / `before:` operators; Google decides what each day returns.

### FAQ

#### Can I get only new articles since the last run?

Yes: set `onlyNewItems` to `true` and run the same input again (for example on a schedule). See **New articles only**.

#### Why did a query return nothing?

An accepted query with no articles in the period returns none. Try a longer `timespan`, fewer words, or another edition. Check the `OUTPUT` record for skipped queries.

#### Why is `articleUrl` empty on a row?

The lookup through Google News did not give that article's publisher URL (it changed shape, or Google refused a request). The row is still returned; `articleUrlReason` says which. The Google News link (`googleNewsUrl`) opens the article too. If every row is empty and the reason says `resolveArticleUrls` is off, turn that input on.

#### Why do I get fewer articles than I asked for?

The feed lists at most 100 articles per request, and a period or an outlet filter can leave fewer. With `splitByDay` one query can go past 100 by walking day by day; without it, widen the period or add another query.

#### Is it legal to use this data?

The Actor reads Google News search results and topic sections that anyone can open, without logging in, and does not open the outlets' pages. Whether you may collect and use this data depends on what you do with it and where you are: Google's terms, the publishers' copyright and the data-protection rules that apply to you are your responsibility. If you republish an article, follow the publisher's terms. This is not legal advice.

### Related Kizuki Actors

Other Actors from Kizuki that work well with this one:

- [Telegram Channel Scraper](https://apify.com/kizukidata/telegram-channel-feed) — channel posts on the same story, with views and reactions.
- [YouTube Channel Scraper](https://apify.com/kizukidata/youtube-channel-monitor) — the video coverage of the same story.

### Your feedback

Bugs, a query that returns the wrong language, and feature requests go to the Actor's **Issues** tab in Apify Console. A publisher who wants its articles left out can open an Issue with the outlet's domain; the exclusion is applied in the next build, and a request from a third party is not enough.

# Actor input Schema

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

Search queries, up to 10, one request each. Google News search syntax works: double quotes for exact phrases, OR between terms, a minus sign to exclude a word, site:example.com for one outlet. An article found by two queries is returned once. When Topics are set and this field is left at its default, only the topics are read.

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

Google News topic sections of the edition, one request each: TOP (top stories), WORLD, NATION, BUSINESS, TECHNOLOGY, ENTERTAINMENT, SPORTS, SCIENCE, HEALTH. Topic rows also list other outlets' coverage of the same story (relatedCoverage). Period does not apply to topics; use Published after.

## `timespan` (type: `string`):

How far back to search: 1 to 48 hours or 1 to 30 days, for example "6h", "24h", "7d", "30d". It is added to each query as Google News' when: operator, unless the query has its own when:.

## `edition` (type: `string`):

Google News edition (country and language) to search. It decides which outlets and which language Google News favours.

## `publishedAfter` (type: `string`):

Keep only articles published at or after this time: an ISO 8601 date or date-time (UTC when no zone is given). Useful for scheduled runs. Articles left out are not charged. Empty keeps all.

## `includeOutlets` (type: `array`):

Keep only articles from these outlets: a domain (matches its subdomains too, for example reuters.com) or the exact outlet name. Up to 50. Articles left out are not charged. Empty keeps all.

## `excludeOutlets` (type: `array`):

Leave out articles from these outlets: a domain (matches its subdomains too) or the exact outlet name. Up to 50. Articles left out are not charged.

## `splitByDay` (type: `boolean`):

Search each query day by day (one request per day, up to 7 days per run in total across queries, newest day first), to get past the feed's 100 articles per request. Days = the Period in days, at most 7 divided by the number of queries; up to 7 queries. Off by default. If Google News answers 'too many requests', the remaining days are skipped and listed in OUTPUT uncheckedInputs.

## `onlyNewItems` (type: `boolean`):

Return only articles that no earlier run with the same queries and edition returned (state kept for 90 days in a named key-value store in your account). The first run returns everything up to maxItems; articles left out by maxItems or the spending limit come back as new next time. Do not run the same input twice at the same time.

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

Maximum number of articles to return across all queries, from 1 to 1000. Each query contributes at most an equal share, in the order the feed lists them (by relevance, not strictly by date), and the feed lists at most 100 articles per query. Each returned article is one charged result.

## `resolveArticleUrls` (type: `boolean`):

Look up the outlet's own article URL for every returned row (the `articleUrl` field) instead of only the Google News link. One extra request per returned row, so a run takes a little longer; a link that cannot be resolved still returns its row with the reason in `articleUrlReason`. Off returns every row with `articleUrl` empty and the reason saying so.

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

Proxy settings. The default uses no proxy. Residential proxies are not available.

## Actor input object example

```json
{
  "queries": [
    "electric vehicles",
    "\"interest rates\""
  ],
  "topics": [
    "TECHNOLOGY"
  ],
  "timespan": "7d",
  "edition": "GB:en",
  "publishedAfter": "2026-11-04T06:00:00Z",
  "includeOutlets": [
    "reuters.com",
    "BBC"
  ],
  "excludeOutlets": [
    "example-press-releases.com"
  ],
  "splitByDay": false,
  "onlyNewItems": true,
  "maxItems": 50,
  "resolveArticleUrls": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

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

News articles returned by this run.

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

Status code, counters and skipped input entries of this run.

# 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": [
        "artificial intelligence"
    ],
    "timespan": "24h",
    "maxItems": 20,
    "resolveArticleUrls": true,
    "proxyConfiguration": {
        "useApifyProxy": false
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("kizukidata/google-news-feed").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": ["artificial intelligence"],
    "timespan": "24h",
    "maxItems": 20,
    "resolveArticleUrls": True,
    "proxyConfiguration": { "useApifyProxy": False },
}

# Run the Actor and wait for it to finish
run = client.actor("kizukidata/google-news-feed").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": [
    "artificial intelligence"
  ],
  "timespan": "24h",
  "maxItems": 20,
  "resolveArticleUrls": true,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}' |
apify call kizukidata/google-news-feed --silent --output-dataset

```

## MCP server setup

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

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/6G99DZ5S5Pj5V8yGB/builds/beUcfzryzdx6n07Sz/openapi.json
