# Google News Scraper — $0.20/1K | Articles & URLs (`monkey.d.scraping/google-news-scraper-lite`) Actor

Search Google News by keyword and date across 13 editions. Export headlines, direct URLs and optional descriptions/images. $0.20/1K + $0.0015/start; platform included.

- **URL**: https://apify.com/monkey.d.scraping/google-news-scraper-lite.md
- **Developed by:** [Monkey D. Scraping](https://apify.com/monkey.d.scraping) (community)
- **Categories:** News, Automation
- **Stats:** 2 total users, 2 monthly users, 69.2% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.20 / 1,000 news records

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?

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 — $0.20/1K | Articles & URLs

Search Google News by **keyword, country edition and publication date**. Export article headlines, publishers, dates, Google News links and matching searches to CSV, Excel or JSON. Add **direct article URLs, publisher descriptions and image URLs** when you need an enriched press review.

Use this Google News scraper for **brand monitoring, competitor news tracking, media monitoring and historical news research** across 13 country/language editions. Custom date ranges can span multiple years, with up to 300 articles per keyword and 20 keywords per run. These are request limits, not guaranteed coverage. No Google News API key is required; programmatic Apify calls use your Apify token.

**Price:** **$0.20 per 1,000 saved news records + $0.0015 per run start**, with platform usage included at 128 MB. Both collection modes have the same result price. Check the current **Pricing** tab before running.

**Two collection modes:** Simple for a quick news feed; Advanced for custom dates, expanded coverage and publisher metadata. Start with ten articles to check the coverage for your keyword.

Automate your news sheet: [Google News to Google Sheets with n8n](#google-news-to-google-sheets-with-n8n), with step-by-step setup and an importable workflow.

### What can you collect?

| Need | Choose | Output |
| --- | --- | --- |
| Recent news headlines | Simple + past day, week or month | Headlines, publishers, publication dates and Google News links |
| Publisher article URLs | Enable Get direct article links | Direct article URLs where resolution succeeds |
| Historical news by date | Advanced + Custom dates + both dates | Matching news across automatically split date windows |
| More than 100 articles per keyword | Advanced + Search more date windows | Up to 300 articles per keyword, subject to available results |
| Descriptions and images | Advanced + Get publisher descriptions and images | Available page metadata, with explicit status for missing fields |

### Common questions

**Can I search Google News across multiple years?** Yes. Use Advanced mode, Custom dates and both date fields. Ranges can cover up to 3,660 days, with no future dates. Google News availability and collection limits mean this is not a complete historical archive.

**Does this include full article text?** No. Optional enrichment returns publisher descriptions and image URLs, not full text or AI summaries. Some publishers block access or expose no usable metadata.

**How much does a test cost?** Up to 10 saved records cost $0.0035 including startup; up to 300 cost $0.0615. Platform usage at 128 MB is included. An empty run still costs $0.0015. Unavailable optional metadata does not make a saved record free.

**Is this the official Google News API?** No. This is an independent Actor accessed through the Apify API. Export its dataset or use the n8n workflow below to update Google Sheets.

### Quick start

1. Replace the example keyword with your brand, company or topic.
2. Keep **Maximum articles per keyword** at 10 for your first test.
3. Choose the country edition and **News from** period, set your run spending cap, then start the Actor.
4. Open the **News headlines** dataset view, check **Collection summary**, and export the dataset as CSV or Excel.

The four main fields are enough for a headlines search. Open **Optional: publisher article links** and enable **Get direct article links** when your workflow needs the publisher URL.

```json
{
  "queries": ["Microsoft"],
  "edition": "en-US",
  "period": "week",
  "maxItemsPerQuery": 10,
  "resolveArticleUrls": false
}
```

The first-run Console example uses the United States / English edition and 10 articles. API requests that omit `edition` or `maxItemsPerQuery` use Italy / Italian and 50 articles per keyword. Keep these fields explicit to reproduce the example. Set `resolveArticleUrls` to `true` when you need direct publisher links.

Choose from the 13 supported country/language editions listed below. The edition selects Google News localization; it does not guarantee that every publisher is based in that country. Headlines retain the language supplied by the source.

### Brand and competitor news: multiple searches, one sheet

For a first press review, collect two related searches in one run. Paste this input in Console, replace the example brands, and set **Maximum cost per run** to **$0.01** in run options:

```json
{
  "mode": "simple",
  "queries": ["Microsoft", "OpenAI"],
  "edition": "en-US",
  "period": "week",
  "maxItemsPerQuery": 10,
  "resolveArticleUrls": false
}
```

This requests up to 10 articles per search, at most 20 unique saved records: **up to $0.0055** including startup at 128 MB. The $0.01 cap is a ceiling, not the expected charge. An empty run still costs $0.0015. Fewer available articles or overlap can reduce the record charge.

In **News headlines**, review the headline, publication date, publisher, **All matching searches** (`matchedQueries`) and Google News link. Export CSV or Excel for a one-off review. To keep a sheet updated, use the [existing n8n workflow](#google-news-to-google-sheets-with-n8n): put both queries in its Configuration node and set `maxTotalChargeUsd` to `0.01`. Its default $0.005 cap is too small for this 20-record example.

The same Google News article ID is saved once per run and retains all matching searches. For example, one row may match both Microsoft and OpenAI: it counts as one article and one record charge, but contributes to both search counts. Separate articles about the same story can remain separate rows. This is a review of returned coverage, not an exhaustive press archive or a verified share-of-voice measurement.

For recurring use, the workflow updates existing IDs and appends new ones. It does not prevent the Actor from collecting and charging for the same article again in later runs. Validate one manual run before setting up your own schedule.

### Choose the result you need

| Your goal | Setting | What to expect |
| --- | --- | --- |
| Review headlines in a spreadsheet | Leave **Get direct article links** off | Headlines, publishers, dates and Google News links; a small first run |
| Link your dashboard to publisher articles | Enable **Get direct article links** | The same news records, with a verified publisher URL where resolution succeeds; unresolved URLs remain null |
| Keep a reusable news sheet | Follow the [n8n guide](#google-news-to-google-sheets-with-n8n) | A workflow that stores and updates rows; the Actor alone does not remember previous runs |

Simple mode returns headlines and optional direct links. Advanced mode can also read descriptions and image URLs from public publisher-page metadata. Neither mode includes full article text, sentiment or automatic alerts. All modes currently cost the same per saved news record; direct links and publisher metadata take additional work.

### Advanced coverage and publisher metadata

Select **Advanced** and enable **Search more date windows** to search beyond a single saturated feed. Articles repeated across windows or keywords are deduplicated within the run. The maximum is 300 articles per keyword; it is a requested limit, not a promised yield. `RUN_SUMMARY` reports `feedsRequested`, `feedsAtCapacity`, `coverageLimitedQueries` and `duplicatesAcrossWindows`. `coverageExhaustive` remains false. `complete` reports processing status, not an exhaustive archive.

```json
{"mode":"advanced","queries":["Microsoft"],"edition":"en-US","period":"week","expandCoverage":true,"maxItemsPerQuery":300}
```

To collect publisher metadata, enable `enrichArticles`. It automatically enables direct links and can process the collected records across **up to 20 keywords × 300 articles**, within the time and spending limits. Descriptions and image URLs may be absent: inspect `enrichmentStatus`, `publisherFetchedAt`, and the enriched/unavailable counts in `RUN_SUMMARY`. TLS failures, timeouts, HTTP refusals and absent metadata are distinguished where observed. A record is charged even when its optional metadata is unavailable. Pages are read up to a bounded prefix; metadata later in a large page can be missed. No full text or paywall bypass is provided.

```json
{"mode":"advanced","queries":["Microsoft"],"edition":"en-US","period":"week","maxItemsPerQuery":50,"enrichArticles":true}
```

Supported editions: Italy/Italian, US/English, UK/English, Germany/German, France/French, Spain/Spanish, Canada/English, Canada/French, Australia/English, India/English, Brazil/Portuguese, Netherlands/Dutch and Japan/Japanese. These select Google News editions, not a guarantee about each publisher's location.

### Three copy-and-paste starting points

**Quick headlines** — 10 recent results, up to $0.0035 including startup:

```json
{"queries":["Microsoft"],"edition":"en-US","period":"week","maxItemsPerQuery":10}
```

**Enriched press review** — up to 300 records, up to $0.0615 including startup:

```json
{"mode":"advanced","queries":["Microsoft"],"edition":"en-US","period":"week","maxItemsPerQuery":300,"expandCoverage":true,"enrichArticles":true,"processingBudgetSeconds":900}
```

**Historical research** — inclusive custom dates, automatically split when needed:

```json
{"mode":"advanced","queries":["\"Mario Calabresi\""],"edition":"it-IT","period":"custom","dateFrom":"2025-01-01","dateTo":"2026-10-17","maxItemsPerQuery":300,"expandCoverage":true,"resolveArticleUrls":false}
```

These are requested maxima, not guaranteed yields. For the two 300-record examples, set a spending cap of $0.07 or higher to allow the full requested output. For enriched runs use a run timeout of at least 930 seconds with the default 900-second processing budget. Existing saved tasks may retain an older 120-second timeout: update their run options for larger collections. No schedule is created automatically.

#### Precise names and optional headline filters

Broad queries such as `Calabresi Milano` can match unrelated news about people from Calabria. Start with `"Mario Calabresi"` for an exact name, and keep wider election-context searches separate if you want both kinds of coverage. `includeTitleTerms: ["Mario Calabresi"]` requires that literal phrase in the headline; `excludeTitleTerms: ["Lotta Continua"]` removes matching headlines. These are case-insensitive lexical filters, not AI classification. They are off by default and may remove relevant articles whose headline does not contain the name. Counts in `filteredByTitleOccurrences` include repeated observations across windows, not unique discarded articles.

#### Understand limits before re-running

Open **Results and limits by query** (`QUERY_SUMMARY`) for each query's article count, item-limit flag, date windows explored, pending windows, saturation and suggested next step. `RUN_SUMMARY.queryResults` contains the same details. A saturated day cannot be subdivided further. At most 16 RSS feeds are fetched per query, and collection has a 120-second budget inside the overall processing budget. Historical windows are visited newest first; a record or time limit may leave older dates unvisited. Narrow the date range and run those windows separately when you need to investigate further. The Actor does not promise all historical articles.

URL resolution uses four workers. Publisher metadata is cached by exact resolved URL (fragment ignored, query parameters preserved), with at most two concurrent metadata requests per host. Legal/contact boilerplate descriptions are discarded conservatively and the next metadata description is tried. Missing optional fields remain explicit; `publisherDescriptionsAvailable` and `publisherImagesAvailable` count them separately. `enriched` means at least one of these fields exists, not necessarily both.

`processingBudgetSeconds` limits work, while the platform timeout is respected with a reserve for saving results. `not_attempted_time_limit` differs from rate-limit and customer-spending-limit statuses. A short timeout can still leave partial data. `complete` refers to processing of the requested bounded output, not exhaustive source coverage. Review it before importing; titles shared by distinct article IDs are not automatically deleted.

Input validation lists all detected issues in one error, including actionable changes, instead of making you discover one constraint per run.

### Measured example: coverage, speed and price

Observed on **16 October 2026**, version **0.1.19**, at 128 MB. These are samples from this Actor, not a guarantee or a head-to-head competitor benchmark.

| Input: Microsoft, en-US, past week | Unique records | Runtime | Result details | Customer price at the listed rate |
| --- | ---: | ---: | --- | ---: |
| Simple, maximum 100 | 100 | 4.24 s | One RSS feed | $0.0215 |
| Advanced, expanded coverage, maximum 300 | 300 | 8.79 s | Seven feeds; 265 repeated records removed across date windows | $0.0615 |
| Advanced, publisher metadata, maximum 50 | 50 | 28.73 s | 50 direct URLs; 36 records with both description and image | $0.0115 |

The expanded sample shared 98 IDs with the simple sample and added 202; two simple-sample IDs were absent after the final limit. Live results change between runs. Fourteen metadata records were unavailable: four timeouts, eight HTTP403, one HTTP401 and one page without metadata. Missing metadata does not waive the saved-record fee. Coverage is not exhaustive.

**Reproduce it:** use the two Advanced JSON examples above. For the baseline use `mode: "simple"`, `queries: ["Microsoft"]`, `edition: "en-US"`, `period: "week"`, `maxItemsPerQuery: 100`, with direct links disabled. Set API run options to `memory=128`, `timeout=120`, and a maximum charge of $0.03, $0.07 or $0.02 respectively. Runtime is the Apify run duration; prices include startup and saved records, not a monthly Apify subscription. Output counts and availability may differ when you repeat the search.

### Ready-to-run example tasks

Open an example below and choose **Try for free** to create your own task in Apify Console, then replace its keywords with your own. All three use the United States / English edition and the past 7 days.

| Example task | What you get | Maximum example cost per run |
| --- | --- | ---: |
| [Monitor brand and competitor news](https://apify.com/monkey.d.scraping/google-news-scraper-lite/examples/monitor-brand-competitor-news) | Microsoft and Google headlines, publishers, dates and verified direct article links; up to 20 records | $0.0055 |
| [Try Google News: 10 AI headlines](https://apify.com/monkey.d.scraping/google-news-scraper-lite/examples/track-ai-industry-news) | Artificial intelligence headlines, publishers, dates and Google News links; up to 10 records | $0.0035 |
| [Get article descriptions and images](https://apify.com/monkey.d.scraping/google-news-scraper-lite/examples/find-news-specific-publishers) | Advanced mode: up to 10 Microsoft news records with direct URLs and optional publisher descriptions/images; unavailable fields are explicit | $0.0035 |

All three saved examples use a **$0.01 run spending cap**. The cap is a limit, not the example charge. Example costs include startup and platform usage. Searches can return fewer records; optional direct links may remain unverified. Repeated runs may include the same articles. Changing the keywords or record limits changes coverage and can change the cost.

### What can you use it for?

- **Brand and competitor monitoring:** collect recent mentions of companies or products for a review dashboard.
- **Media research:** compare headlines and publishers covering the same topic.
- **Market intelligence:** follow industry, technology or economic news in a selected edition.
- **News automation:** export structured records or pass them to the next step of an API workflow.

Repeated runs collect matching news again. This version deduplicates within a run; it does not remember previously collected articles or emit only new mentions.

### Check news quality before importing

Read `RUN_SUMMARY.complete` before sending results to a reporting workflow. If some feed items have invalid dates, missing required fields or invalid article identifiers, verified articles remain available but `complete` is false. `invalidFeedItems` counts rejected item occurrences across fetched feeds; `queriesWithInvalidItems` counts affected searches. In expanded coverage, the same malformed source item may be encountered in more than one date window, so this is not a unique-article count.

A genuinely empty, verified feed is different from a feed containing rejected items. The supplied n8n workflow already stops on incomplete output before writing to Google Sheets. Inspect the existing results and summary before retrying: another run may collect and charge for the same valid articles again. Even `complete: true` does not mean exhaustive coverage; check feed saturation and collection limits separately.

### Output

| Field | Meaning |
| --- | --- |
| `title` | Headline supplied by Google News |
| `publisher` | Source publication |
| `publishedAt` | Publication timestamp supplied by the feed, normalized to UTC |
| `articleUrl` | Verified publisher article link when requested and resolved; otherwise null |
| `articleUrlResolved` | Whether the direct article link was verified |
| `articleUrlStatus` | Resolution status or reason it could not be verified |
| `googleNewsUrl` | Original Google News article link |
| `publisherHomepage` | Publisher homepage, separate from the article link |
| `matchedQueries` | Keywords that matched the same news item in this run |
| `collectedAt` | Collection time in UTC |

Example output shape (illustrative values):

```json
{
  "title": "Example company announces a new product",
  "publisher": "Example Publisher",
  "publishedAt": "2026-10-10T08:00:00+00:00",
  "articleUrl": "https://publisher.example/news/new-product",
  "articleUrlResolved": true,
  "articleUrlStatus": "resolved",
  "matchedQueries": ["example company"],
  "edition": "en-US"
}
```

With direct links disabled, `articleUrl` is null and `articleUrlStatus` is `not_requested`. The original `googleNewsUrl` is included in both modes. With direct links enabled, results are saved in small batches as links are processed; arrival order can differ from publication order. Sort by `publishedAt` if your workflow needs newest-first output.

### Search examples

| Goal | Keyword or topic |
| --- | --- |
| Follow a brand | `Microsoft` |
| Follow a company with several words | `"example company"` |
| Focus on a publication | `bitcoin site:reuters.com` |
| Follow an industry topic | `renewable energy` |

Use **News from** for the past 24 hours, 7 days or 30 days. In Advanced mode, choose **Custom dates** and set `dateFrom` and `dateTo` (inclusive UTC dates, at most 3660 days, starting in 1970 or later and ending no later than today; intervals longer than 366 days are automatically split). Inline `when:`, `before:` and `after:` operators are rejected to keep the chosen period consistent. Google News determines matching and coverage; requesting 100 articles does not guarantee 100 results.

### Limits and incomplete results

Runs accept up to 20 keywords. Simple mode supports 100 articles per keyword; Advanced with `expandCoverage` supports up to 300. Searches can return fewer articles than requested. Direct links and metadata no longer have a separate requested-record cap. They process the collected records within `processingBudgetSeconds` (default 900, range 60–3600). Choose a small first run to measure availability and time before requesting thousands of records.

A direct link is retained only when its publisher hostname matches the source declared by the feed. That checks attribution, not the article's availability or full text. Missing, blocked or mismatched links remain null. If requested data cannot be verified, the run reports a failure and preserves any collected records. Check `RUN_SUMMARY` for completeness before using partial results.

Dates outside the selected period are filtered. A valid empty search is distinguished from an HTTP or parsing failure. This Actor does not provide full article text, exhaustive historical coverage or unrestricted pagination. Image URLs are optional metadata observations; image files are not downloaded. No API key or login is required.

### Export and integrations

Use the Apify dataset to export JSON, CSV or Excel. An API workflow, n8n or Make can start the Actor and read its dataset using their Apify integration or HTTP modules. Use the returned fields for your dashboard or processing step; sentiment analysis and summaries are not included in this Actor.

### Frequently asked questions

**Can I use this as a Google News API?** Yes. Start the Actor through the Apify API and read its dataset. This is an independent scraper, not an official Google API.

**Can it monitor brand mentions automatically?** Schedule repeated runs on Apify and use the dataset in your workflow. This version does not remember articles between runs; repeated articles can reappear.

**Does it return direct article URLs?** When requested, successfully verified publisher links are returned in `articleUrl`. Unverified links remain null and the run reports incomplete requested data.

**Does the date filter check article content?** No. It uses the publication date supplied by Google News. It does not verify dates inside publisher pages.

**Is this Google Search scraping?** It collects Google News results. It does not collect Google.com organic search results.

**What does it cost?** $0.20 per 1,000 news records saved to the dataset, plus $0.0015 per run start. Platform usage is included. Both modes have the same result price. A result fee covers a news record; it does not guarantee that an optional publisher link can be resolved. The startup fee also applies to empty searches and failed runs.

**Can I cap the cost?** Set Maximum cost per run in Apify Console, or `maxTotalChargeUsd` through the API. The minimum run budget is $0.0017. A $0.0025 budget covers the startup fee and up to five news records. The Actor limits collection to the available result budget and stops when it is exhausted. Budget-limited or aborted runs may contain partial results. Charges apply only to records saved within the budget.

#### Can I choose exact start and end dates?

Yes. Select Advanced mode, choose Custom dates and provide `dateFrom` and `dateTo`. Both endpoints are inclusive in UTC, up to 3660 days, from 1970 onward and no future dates. Intervals longer than 366 days are automatically split into disjoint windows, newest first. The Actor checks feed publication dates locally. A date range does not guarantee a complete historical archive; enable `expandCoverage` to subdivide saturated feeds into smaller date windows. This uses at most 16 feeds per keyword and stops at the result or time limit. Even a single day can be saturated; coverage is never guaranteed exhaustive.

#### Does the selected country restrict every publisher to that country?

No. Country and language select a Google News edition. The source determines matching and publishers, and headlines retain their original language.

#### How do I report missing or unresolved data?

Open the Issues tab with your run ID, non-sensitive query, edition and expected result. Review `RUN_SUMMARY` and `articleUrlStatus` first. A publisher homepage is not a substitute for an unresolved article URL.

### Price examples

| Delivered news records | Total run charge |
| --- | ---: |
| 0 | $0.0015 |
| 10 | $0.0035 |
| 100 | $0.0215 |
| 200 | $0.0415 |

These are charges for one run at 128 MB. The price is the same across Apify plans; Free-plan users spend their available Apify credits. Repeated scheduled runs incur a startup fee each time.

### Google News to Google Sheets with n8n

Build a brand monitoring sheet with Google News headlines, publishers, publication dates and article links. This workflow uses [Google News Scraper](https://apify.com/monkey.d.scraping/google-news-scraper-lite) and built-in n8n nodes; you do not need a community node or a Google News API key.

Start with **Microsoft, United States, past week, up to 10 articles**. The Actor charge is at most **$0.0035 per run** at the current list price, with a **$0.005 run spending cap**. The workflow runs manually until you choose to add a schedule.

#### What you need

- An Apify account with available credits and an API token.
- An n8n instance with HTTP Request, Code and Google Sheets nodes. Import and local execution were verified with **n8n 2.42.6**; older versions may require updating node versions or mapping.
- A Google Sheet you can edit and a Google Sheets OAuth2 credential configured in n8n. Follow [n8n’s Google Sheets credential guide](https://docs.n8n.io/integrations/builtin/credentials/google/).

#### 1. Prepare the sheet

Create a tab named **News**. Paste these tab-separated column names into cell A1, all on the first row:

```text
id	title	publisher	publishedAt	articleUrl	googleNewsUrl	matchedQueries	edition	collectedAt	articleUrlStatus
```

Keep the headers exactly as shown. Keep `id` as text and unique. Avoid blank rows inside the table and concurrent workflows writing to this tab. The Google Sheets credential must have edit access to this document.

Your spreadsheet ID is the part between `/d/` and `/edit` in its URL. For example, in `https://docs.google.com/spreadsheets/d/YOUR_ID/edit`, use `YOUR_ID`.

#### 2. Import the workflow

Save the supplied **google-news-to-google-sheets.n8n.json** file and select **Import from File** in n8n. On the Actor’s public README, the same workflow is available in the **Importable workflow JSON** section: copy the JSON, save it as a `.json` file, and import it. [n8n import instructions](https://docs.n8n.io/workflows/export-import/).

Open **Configuration** and replace `PASTE_YOUR_SPREADSHEET_ID` with your document ID. You can edit keywords, country, time period and record limit in this single node. Keep the default configuration for your first test:

```json
{
  "queries": ["Microsoft"],
  "edition": "en-US",
  "period": "week",
  "maxItemsPerQuery": 10,
  "resolveArticleUrls": false,
  "maxTotalChargeUsd": 0.005,
  "spreadsheetId": "PASTE_YOUR_SPREADSHEET_ID",
  "sheetName": "News"
}
```

This bundled workflow retains the simple collection configuration; it does not export advanced publisher metadata or custom dates. Choose the Google News edition explicitly: `en-US`, `en-GB`, `it-IT`, `de-DE`, `fr-FR` or `es-ES`. Period accepts `day`, `week` or `month`. The workflow checks your configuration before starting a paid run.

#### 3. Connect credentials

In any of the four HTTP Request nodes, create a **Bearer Auth** credential. Enter your Apify token in the token field, without adding a `Bearer ` prefix. Select this same credential in **Start Actor**, **Wait for Run**, **Get Run Summary** and **Get Dataset Items**.

Keep the token in n8n credentials; do not paste it into the workflow JSON, a query string or the Configuration node. [Apify API authentication](https://docs.apify.com/api/v2).

In **Save News to Google Sheets**, select your Google Sheets OAuth2 credential. Verify these settings:

| Setting | Value |
|---|---|
| Operation | Append or Update Row |
| Document | ID from Configuration |
| Sheet | News, or the name from Configuration |
| Mapping | Map Automatically |
| Column to match on | id |
| Cell format | RAW |

If the editor asks you to refresh column mappings, refresh them after selecting the document and tab, then keep `id` as the matching column. RAW stores strings as data, including headlines that start with an equals sign. [Google Sheets node operations](https://docs.n8n.io/integrations/builtin/app-nodes/n8n-nodes-base.googlesheets/sheet-operations/).

#### 4. Run a first test

Click **Execute Workflow**. The flow:

Manual run → check configuration → run Actor → verify complete output → map news → append or update rows by article ID.

The default example returns up to 10 records, not a guaranteed 10: Google News may have fewer matching articles. Publication dates and collection timestamps remain ISO strings in the sheet. `matchedQueries` is flattened into a text field.

With direct links disabled, `articleUrl` is empty and `googleNewsUrl` is your usable news link. Enable `resolveArticleUrls` if you need verified publisher article URLs. This takes longer; the sample workflow keeps a conservative 200-requested-record limit and 120-second run timeout. The Actor itself supports larger inputs with a longer time budget. The workflow rejects incomplete output if any requested links cannot be verified. Article bodies and paywalled content are not included.

The Actor deduplicates overlapping queries within one run. The sheet additionally matches `id` across runs: existing IDs are updated, new IDs are appended. This does not remove pre-existing duplicate rows or save Actor charges on repeated collection. Metadata and matched queries for an existing row are replaced by the latest run’s values; this is a current monitoring sheet, not an immutable event log.

#### Costs and scheduling

At the current list price, the Actor charges **$0.0015 per start + $0.0002 per saved news record**, including Actor platform usage at the prescribed 128 MB. Startup also applies when no articles are returned. n8n hosting and any separate storage/read/transfer charges are outside this estimate; check current pricing before enabling a schedule.

| Configuration | Maximum Actor charge per run | 30 runs, one per day |
|---|---:|---:|
| 1 keyword × 10 records | $0.0035 | $0.105 |
| 2 keywords × 10 records | $0.0055 | $0.165 |
| 1 keyword × 100 records | $0.0215 | $0.645 |

Set `maxTotalChargeUsd` at least as high as the configured maximum: `0.0015 + 0.0002 × keywords × maxItemsPerQuery`. For two keywords with 10 articles each, a cap of `$0.01` is sufficient. Overlapping queries can reduce the saved count and charge. The default `$0.005` cap covers the default single-keyword example.

After one successful manual run, you may replace the Manual Trigger with a **Schedule Trigger**, choose your timezone and run once daily. Publish/activate only when you are ready for repeated charges. The supplied workflow is inactive and contains no schedule.

#### Errors and recovery

- **Configuration error:** no Actor is started. Fix the document ID, input or spending cap first.
- **Run is RUNNING/READY:** the two API calls wait up to 60 seconds each. Open the given run ID in Apify Console. If it is still running, wait for completion and retrieve that run’s outputs; do not retry Start Actor just to download them.
- **FAILED, TIMED-OUT or ABORTED:** inspect the run log and `RUN_SUMMARY`; the workflow stops before writing to Sheets. A start fee and charges for already saved records may still apply.
- **Incomplete/budget-limited output:** the workflow stops instead of silently exporting a partial set. Inspect the summary before deliberately retrying with another budget.
- **No results:** a complete empty run leaves the sheet unchanged; this is not necessarily an error.
- **Google Sheets permission/header error:** fix access or headers. Reuse the successful run’s dataset rather than launching another paid run. If a write was partly completed, reprocessing the same dataset with matching `id` updates those rows instead of adding another copy, provided the sheet has unique IDs and no concurrent writer.
- **Network error on Start Actor:** automatic retries are disabled for the POST. Check whether Apify created a run before launching another one. GET requests retry safely up to three times.

#### Validation scope

The default input was run against the released Apify Actor on 10 October 2026: 10 records, `complete: true`. The importable JSON was imported into n8n 2.42.6 and executed with those real output shapes against a local mock API, through the sheet boundary. Additional tests exercise the official Google Sheets node with mocked transport: append, update on a repeat run, and RAW value handling. Tests also reject failed/pending runs, partial output, duplicate IDs and an insufficient spending cap.

**A live write to a user-owned Google Sheet has not been tested.** Your OAuth credential and sheet must be connected for that final check. No token, credential ID, sheet ID or customer data is included in the template.

#### More ready-to-run monitoring examples

| Use case | Example |
|---|---|
| Track brands and competitors | [Microsoft and Google news](https://apify.com/monkey.d.scraping/google-news-scraper-lite/examples/monitor-brand-competitor-news) |
| Follow AI industry headlines | [Artificial intelligence news](https://apify.com/monkey.d.scraping/google-news-scraper-lite/examples/track-ai-industry-news) |
| Try publisher metadata separately from this simple workflow | [Article descriptions and images](https://apify.com/monkey.d.scraping/google-news-scraper-lite/examples/find-news-specific-publishers) |

For search interest over time, see [Google Trends Keyword History](https://apify.com/monkey.d.scraping/google-trends-keyword-analysis). For public-channel updates, see [Telegram New Posts Monitor](https://apify.com/monkey.d.scraping/telegram-new-posts-monitor-channel-discovery). These are separate Actors with their own pricing.

#### Importable workflow JSON

Copy the JSON below into a `.json` file and import it in n8n.

```json
{
  "name": "Google News to Google Sheets — budget-capped brand monitoring",
  "nodes": [
    {
      "id": "news-1",
      "name": "Manual Trigger",
      "type": "n8n-nodes-base.manualTrigger",
      "typeVersion": 1,
      "position": [
        0,
        200
      ],
      "parameters": {}
    },
    {
      "id": "news-2",
      "name": "Configuration",
      "type": "n8n-nodes-base.set",
      "typeVersion": 3.4,
      "position": [
        240,
        200
      ],
      "parameters": {
        "mode": "raw",
        "jsonOutput": "{\n  \"queries\": [\n    \"Microsoft\"\n  ],\n  \"edition\": \"en-US\",\n  \"period\": \"week\",\n  \"maxItemsPerQuery\": 10,\n  \"resolveArticleUrls\": false,\n  \"maxTotalChargeUsd\": 0.005,\n  \"spreadsheetId\": \"PASTE_YOUR_SPREADSHEET_ID\",\n  \"sheetName\": \"News\"\n}",
        "options": {}
      },
      "notes": "Edit queries and spreadsheetId here. Default: at most 10 records, $0.005 run cap, US edition. No schedule is enabled.",
      "notesInFlow": true
    },
    {
      "id": "news-3",
      "name": "Validate Configuration",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        480,
        200
      ],
      "parameters": {
        "jsCode": "const c = $input.first().json;\nif (!c.spreadsheetId || c.spreadsheetId === 'PASTE_YOUR_SPREADSHEET_ID') throw new Error('Set spreadsheetId in Configuration before running.');\nif (!Array.isArray(c.queries) || !c.queries.length || c.queries.length > 20 || c.queries.some(q => typeof q !== 'string' || !q.trim())) throw new Error('Provide 1–20 non-empty queries.');\nif (!Number.isInteger(c.maxItemsPerQuery) || c.maxItemsPerQuery < 1 || c.maxItemsPerQuery > 100) throw new Error('maxItemsPerQuery must be 1–100.');\nif (typeof c.resolveArticleUrls !== 'boolean') throw new Error('resolveArticleUrls must be true or false.');\nif (!['en-US','en-GB','it-IT','de-DE','fr-FR','es-ES'].includes(c.edition) || !['day','week','month'].includes(c.period)) throw new Error('Choose a supported edition and period.');\nif (!Number.isFinite(c.maxTotalChargeUsd) || c.maxTotalChargeUsd < 0.0017) throw new Error('Run cap must be at least $0.0017.');\nconst maxRows = c.queries.length * c.maxItemsPerQuery;\nif (c.resolveArticleUrls && maxRows > 200) throw new Error('Direct links support at most 200 requested records per run.');\nconst estimatedMaximum = 0.0015 + maxRows * 0.0002;\nif (c.maxTotalChargeUsd + 1e-10 < estimatedMaximum) throw new Error('Cap is below the configured maximum ($' + estimatedMaximum.toFixed(4) + '). Reduce records or increase the cap.');\nreturn [{json:c}];"
      }
    },
    {
      "id": "news-4",
      "name": "Start Actor",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        720,
        200
      ],
      "parameters": {
        "method": "POST",
        "url": "https://api.apify.com/v2/actors/monkey.d.scraping~google-news-scraper-lite/runs",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "options": {
          "timeout": 75000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "waitForFinish",
              "value": "60"
            },
            {
              "name": "timeout",
              "value": "120"
            },
            {
              "name": "memory",
              "value": "128"
            },
            {
              "name": "build",
              "value": "latest"
            },
            {
              "name": "restartOnError",
              "value": "false"
            },
            {
              "name": "maxTotalChargeUsd",
              "value": "={{ $json.maxTotalChargeUsd }}"
            }
          ]
        },
        "sendBody": true,
        "specifyBody": "json",
        "jsonBody": "={{ JSON.stringify({queries:$json.queries, edition:$json.edition, period:$json.period, maxItemsPerQuery:$json.maxItemsPerQuery, resolveArticleUrls:$json.resolveArticleUrls}) }}"
      },
      "retryOnFail": false,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "notes": "Select the same Apify Bearer Auth credential on all four HTTP nodes. Never enable automatic retries on Start Actor: a repeated POST can start and bill another run.",
      "notesInFlow": false
    },
    {
      "id": "news-5",
      "name": "Wait for Run",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        960,
        200
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://api.apify.com/v2/actor-runs/{{ $json.data.id }}",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "options": {
          "timeout": 75000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "waitForFinish",
              "value": "60"
            }
          ]
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "notes": "Select the same Apify Bearer Auth credential on all four HTTP nodes. Never enable automatic retries on Start Actor: a repeated POST can start and bill another run.",
      "notesInFlow": false
    },
    {
      "id": "news-6",
      "name": "Validate Run",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1200,
        200
      ],
      "parameters": {
        "jsCode": "const r = $input.first().json.data;\nif (!r?.id) throw new Error('Missing Apify run ID.');\nif (r.status !== 'SUCCEEDED') throw new Error('Apify run ' + r.id + ' is ' + r.status + '. Inspect it in Console. If still running, resume with Wait for Run using this ID after it finishes; do not restart Start Actor to fetch the same results.');\nif (!r.defaultDatasetId || !r.defaultKeyValueStoreId) throw new Error('Run has no output storage IDs.');\nreturn [{json:r}];"
      }
    },
    {
      "id": "news-7",
      "name": "Get Run Summary",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1440,
        200
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://api.apify.com/v2/key-value-stores/{{ $json.defaultKeyValueStoreId }}/records/RUN_SUMMARY",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "options": {
          "timeout": 75000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "notes": "Select the same Apify Bearer Auth credential on all four HTTP nodes. Never enable automatic retries on Start Actor: a repeated POST can start and bill another run.",
      "notesInFlow": false
    },
    {
      "id": "news-8",
      "name": "Check Complete Output",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1680,
        200
      ],
      "parameters": {
        "jsCode": "const s = $input.first().json;\nif (s.complete !== true || s.budgetLimited === true || s.queriesFailed > 0 || s.queriesSkipped > 0) throw new Error('Apify output is partial or unverified. Inspect RUN_SUMMARY before exporting. No sheet rows were written.');\nif (!Number.isInteger(s.savedRows) || s.savedRows < 0) throw new Error('Invalid savedRows in RUN_SUMMARY.');\nreturn [{json:{datasetId:$('Validate Run').first().json.defaultDatasetId, expectedRows:s.savedRows}}];"
      }
    },
    {
      "id": "news-9",
      "name": "Get Dataset Items",
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.2,
      "position": [
        1920,
        200
      ],
      "parameters": {
        "method": "GET",
        "url": "=https://api.apify.com/v2/datasets/{{ $json.datasetId }}/items",
        "authentication": "genericCredentialType",
        "genericAuthType": "httpBearerAuth",
        "options": {
          "timeout": 75000,
          "response": {
            "response": {
              "responseFormat": "json"
            }
          }
        },
        "sendQuery": true,
        "queryParameters": {
          "parameters": [
            {
              "name": "clean",
              "value": "true"
            },
            {
              "name": "format",
              "value": "json"
            },
            {
              "name": "limit",
              "value": "2000"
            }
          ]
        }
      },
      "retryOnFail": true,
      "maxTries": 3,
      "waitBetweenTries": 1000,
      "notes": "Select the same Apify Bearer Auth credential on all four HTTP nodes. Never enable automatic retries on Start Actor: a repeated POST can start and bill another run.",
      "notesInFlow": false
    },
    {
      "id": "news-10",
      "name": "Prepare Sheet Rows",
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        2160,
        200
      ],
      "parameters": {
        "jsCode": "const input = $input.all();\nconst rows = input.flatMap(i => Array.isArray(i.json) ? i.json : [i.json]);\nconst expected = $('Check Complete Output').first().json.expectedRows;\nif (rows.length !== expected) throw new Error('Dataset row count mismatch; no rows exported.');\nconst seen = new Set();\nreturn rows.map(r => {\n  if (typeof r.id !== 'string' || !r.id || seen.has(r.id)) throw new Error('Missing or duplicate article ID.');\n  seen.add(r.id);\n  const keys = ['id','title','publisher','publishedAt','articleUrl','googleNewsUrl','edition','collectedAt','articleUrlStatus'];\n  const out = Object.fromEntries(keys.map(k => [k, r[k] == null ? '' : String(r[k])]));\n  out.matchedQueries = Array.isArray(r.matchedQueries) ? r.matchedQueries.join(' | ') : String(r.query ?? '');\n  return {json:out};\n});"
      }
    },
    {
      "id": "news-11",
      "name": "Save News to Google Sheets",
      "type": "n8n-nodes-base.googleSheets",
      "typeVersion": 4.6,
      "position": [
        2400,
        200
      ],
      "parameters": {
        "resource": "sheet",
        "operation": "appendOrUpdate",
        "documentId": {
          "__rl": true,
          "value": "={{ $('Configuration').first().json.spreadsheetId }}",
          "mode": "id"
        },
        "sheetName": {
          "__rl": true,
          "value": "={{ $('Configuration').first().json.sheetName }}",
          "mode": "name"
        },
        "columns": {
          "mappingMode": "autoMapInputData",
          "value": {},
          "matchingColumns": [
            "id"
          ],
          "schema": [
            {
              "id": "id",
              "displayName": "id",
              "required": false,
              "defaultMatch": true,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "title",
              "displayName": "title",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "publisher",
              "displayName": "publisher",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "publishedAt",
              "displayName": "publishedAt",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "articleUrl",
              "displayName": "articleUrl",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "googleNewsUrl",
              "displayName": "googleNewsUrl",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "matchedQueries",
              "displayName": "matchedQueries",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "edition",
              "displayName": "edition",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "collectedAt",
              "displayName": "collectedAt",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            },
            {
              "id": "articleUrlStatus",
              "displayName": "articleUrlStatus",
              "required": false,
              "defaultMatch": false,
              "display": true,
              "type": "string",
              "canBeUsedToMatch": true
            }
          ],
          "attemptToConvertTypes": false,
          "convertFieldsToString": false
        },
        "options": {
          "cellFormat": "RAW",
          "handlingExtraData": "ignoreIt"
        }
      },
      "notes": "Select your Google Sheets OAuth2 credential. Create the News tab with the exact headers from the tutorial. Append or Update matches id; RAW stores headlines as text.",
      "notesInFlow": true
    }
  ],
  "connections": {
    "Manual Trigger": {
      "main": [
        [
          {
            "node": "Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Configuration": {
      "main": [
        [
          {
            "node": "Validate Configuration",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Configuration": {
      "main": [
        [
          {
            "node": "Start Actor",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Start Actor": {
      "main": [
        [
          {
            "node": "Wait for Run",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Wait for Run": {
      "main": [
        [
          {
            "node": "Validate Run",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Validate Run": {
      "main": [
        [
          {
            "node": "Get Run Summary",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Run Summary": {
      "main": [
        [
          {
            "node": "Check Complete Output",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Check Complete Output": {
      "main": [
        [
          {
            "node": "Get Dataset Items",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Get Dataset Items": {
      "main": [
        [
          {
            "node": "Prepare Sheet Rows",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Prepare Sheet Rows": {
      "main": [
        [
          {
            "node": "Save News to Google Sheets",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": false,
  "settings": {
    "executionOrder": "v1"
  },
  "pinData": {},
  "tags": [],
  "id": "googleNewsSheetsTemplate"
}
```

### More Actors by Monkey D. Scraping

Combine news research with these complementary tools from the same developer. Each Actor runs separately with its own inputs and pricing.

| Recommended Actor | When to use it |
| --- | --- |
| [Google Trends Scraper — Keyword History API](https://apify.com/monkey.d.scraping/google-trends-keyword-analysis) | Compare news coverage with keyword search-interest history by country and period. |
| [Telegram New Posts Monitor & Channel Discovery](https://apify.com/monkey.d.scraping/telegram-new-posts-monitor-channel-discovery) | Follow new posts from public Telegram channels using saved task checkpoints, alongside your news-monitoring workflow. |

### If a dataset write cannot be confirmed

The Actor stops further dataset writes with `POST_STORAGE_UNCONFIRMED` after a storage, billing acknowledgement or cancellation error. Other workers and the abort handler do not resubmit the uncertain batch. Records from earlier acknowledged batches remain available.

An error can occur after the platform accepted a batch, so a failed run does not prove that it saved no records or incurred no charges. Inspect the existing dataset before starting a separate run and deduplicate by `id`. A storage failure can prevent the final `RUN_SUMMARY` from being saved; the Actor does not treat that run as complete.

### Why do query counts differ from the number of news rows?

An article found by several searches is saved once. `query` is the first associated search, not a complete count of matches. Use every value in `matchedQueries` when grouping articles by search; those per-search counts can add up to more than the number of unique articles. These are matches returned by Google News, not an independent check that the exact phrase appears in the headline or refers to the intended person.

The default **News headlines** view puts all matching searches and the available Google News link next to the headline. Open **Publisher links and metadata** for optional direct links, descriptions, images and their status, or **All article fields** for the complete record.

If `resolveArticleUrls` is false, `articleUrl` is null and `articleUrlStatus` is `not_requested` by design. Open `googleNewsUrl` to read the Google News result. `publisherHomepage` is the publication homepage, not the article. Selecting an output view does not enable URL resolution or enrichment and does not change charges.

### Real observed output excerpt

Reduced record from an owner verification run observed on 19 October 2026. Field values are retained from that observation and may have changed since then.

```json
{
  "query": "Microsoft",
  "matchedQueries": [
    "Microsoft"
  ],
  "title": "Lifetime access to Microsoft Word, Excel, PowerPoint, and more is now just $49.97 - PCWorld",
  "publishedAt": "2026-10-19T08:05:58+00:00",
  "publisher": "PCWorld",
  "googleNewsUrl": "https://news.google.com/rss/articles/CBMivwFBVV95cUxPZWpJU29YaW1zcF9YamNhYmk5aHU0elZhSHloQm9kRzZuckhXSlhrUWNRVmlKS3dHRzkxZ0VQY1ZjWTJKTEJycWk2WVNfSV9YOXJia2pBa0pCSE52QVA1MXFpWmIxS1cydFZiMFRYT18wVFBRa3ZvSE02RFlKWThRWVV0STlNVmI5Vzd2VkJwdzJpM2pzUWRaSFAtdnNiOS1rTHdBV2tQQUhVbGN4MlAwNDl5cnozdWFRQlpDY3U4RQ?oc=5",
  "articleUrl": null,
  "articleUrlResolved": false,
  "articleUrlStatus": "not_requested",
  "edition": "en-US",
  "collectedAt": "2026-10-19T10:51:11.195424+00:00",
  "source": "google-news-rss"
}
```

Other fields are omitted here. The article URL is null because resolution was not requested, not because resolution failed. Use googleNewsUrl as the source link in this mode. The headline is publisher content, not a verified commercial offer. matchedQueries reports searches associated with this saved item; it does not prove complete news coverage.

# Actor input Schema

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

One company, person or topic per line, up to 20. For an exact name, include quotation marks, e.g. "Microsoft". Matching articles are deduplicated across searches.

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

Select a Google News country edition and its language together.

## `period` (type: `string`):

Choose a rolling period, or Custom dates with advanced mode. Custom dates are inclusive in UTC.

## `maxItemsPerQuery` (type: `integer`):

Start with 10 (up to $0.0035 including startup for one keyword). Above 100, choose Advanced and enable Search more date windows. Maximum 300 per keyword; results depend on availability.

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

Simple: recent headlines and optional direct links, up to 100 per keyword. Advanced: custom dates, up to 300 with expanded coverage, and optional descriptions/images.

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

Resolve publisher links for the collected records, up to 20 keywords × 300 articles with expanded coverage. Uses the processing time budget; unavailable links stay empty with an explicit status.

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

Advanced + Custom dates. Both dates required, from 1970 onward, up to 3660 days and no future dates. Ranges longer than 366 days are automatically split into consecutive windows.

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

Inclusive final date in UTC. Choose Custom dates above and provide both dates.

## `expandCoverage` (type: `boolean`):

Required above 100 articles per keyword. Choose Advanced first. Searches additional date windows, up to 16 feeds per keyword, and removes duplicate article IDs. More results are not guaranteed.

## `enrichArticles` (type: `boolean`):

Advanced mode. Automatically resolves direct links, then reads publisher descriptions and images for collected records within the processing time budget. Identical URLs share a metadata fetch. Unavailable fields remain empty. No full article text.

## `processingBudgetSeconds` (type: `integer`):

Default 15 minutes; new runs have a 16-minute timeout. Older saved tasks may still use 120 seconds: increase their run timeout for larger enriched searches. If you raise this budget, set the timeout at least 30 seconds higher. Maximum cost per run is a separate spending limit.

## `includeTitleTerms` (type: `array`):

Optional literal words or phrases, case-insensitive. A headline must contain at least one; leave empty to keep all. Example: Mario Calabresi. Applied before saving and charging.

## `excludeTitleTerms` (type: `array`):

Optional literal words or phrases, case-insensitive. Matching headlines are excluded before saving and charging. Filtering counts appear in the summary.

## Actor input object example

```json
{
  "queries": [
    "Microsoft"
  ],
  "edition": "en-US",
  "period": "week",
  "maxItemsPerQuery": 10,
  "mode": "simple",
  "resolveArticleUrls": false,
  "expandCoverage": false,
  "enrichArticles": false,
  "processingBudgetSeconds": 900
}
```

# Actor output Schema

## `overview` (type: `string`):

Unique headlines, all matching searches and Google News links. Optional fields are available in the dedicated dataset view.

## `news` (type: `string`):

Headlines, publishers, dates, optional direct article links and optional publisher descriptions/images with explicit status.

## `summary` (type: `string`):

Check completeness, saved and charged records, customer budget limits and direct-link status.

## `queries` (type: `string`):

Per-query counts, reached limits, explored/pending date windows and next steps. Coverage is never exhaustive.

# 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": [
        "Microsoft"
    ],
    "edition": "en-US",
    "period": "week",
    "maxItemsPerQuery": 10,
    "mode": "simple",
    "resolveArticleUrls": false,
    "expandCoverage": false,
    "enrichArticles": false
};

// Run the Actor and wait for it to finish
const run = await client.actor("monkey.d.scraping/google-news-scraper-lite").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": ["Microsoft"],
    "edition": "en-US",
    "period": "week",
    "maxItemsPerQuery": 10,
    "mode": "simple",
    "resolveArticleUrls": False,
    "expandCoverage": False,
    "enrichArticles": False,
}

# Run the Actor and wait for it to finish
run = client.actor("monkey.d.scraping/google-news-scraper-lite").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": [
    "Microsoft"
  ],
  "edition": "en-US",
  "period": "week",
  "maxItemsPerQuery": 10,
  "mode": "simple",
  "resolveArticleUrls": false,
  "expandCoverage": false,
  "enrichArticles": false
}' |
apify call monkey.d.scraping/google-news-scraper-lite --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,monkey.d.scraping/google-news-scraper-lite"
        }
    }
}
```

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/a5xfMzCmkvgPiMrH3/builds/EUMMYAWFyvj2jDZiM/openapi.json
