# Google News Search — From $0.35/1K — Headlines & Publishers (`apivault_labs/google-news-search`) Actor

Search public Google News RSS by keyword and locale. Export deduplicated headlines, publisher metadata, dates and Google News links with bounded coverage and source diagnostics.

- **URL**: https://apify.com/apivault_labs/google-news-search.md
- **Developed by:** [Apivault Labs](https://apify.com/apivault_labs) (community)
- **Categories:** News
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.35 / 1,000 article delivereds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
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 Search: headlines, publishers and publication dates

![Google News Search — conceptual news collection illustration](https://raw.githubusercontent.com/apivault-labs/apivault-labs/main/assets/google-news-search/hero.jpg)

*Concept illustration; article images are not downloaded.*

Collect structured Google News metadata from keyword searches or category feeds for brand monitoring, industry research and news discovery. Enter a search phrase to receive headlines, publishers, publication dates and Google News article links. No Google account, external API key or proxy configuration is required.

Article events cost **$0.35–$0.50 per 1,000 delivered articles depending on your Apify pricing tier**, with **no start fee**. Apify platform usage is charged separately. Begin with five rows: article events cost at most $0.0025 at the listed rates, plus platform usage.

### Start with five headlines

```json
{
  "queries": ["OpenAI"],
  "maxResults": 5
}
```

Run the actor, then open the Dataset. Each row represents one article. Download JSON, CSV or Excel through Apify. Open the `SUMMARY` key-value record to see which queries were processed and whether a limit was reached; `ERRORS` contains diagnostic records.

### What you can collect

| Need | Supported behavior |
|---|---|
| Brand or company news | Search one or more phrases in the public Google News RSS feed |
| Industry research | Collect headlines and publisher metadata for topic queries |
| Regional news | Set a language and country, such as French / France |
| A publication window | Filter the returned snapshot by UTC publication date |
| Several search terms | Merge results and deduplicate identical Google News article paths |
| Export for an analyst or agent | Stable field names, explicit missing values and separate diagnostics |

Each RSS feed supplies a bounded snapshot, commonly up to approximately 100 items. Snapshot mode reads one feed per query; daily mode requests separate date-restricted feeds and merges their results. Neither mode is an exhaustive news archive. A local date filter cannot restore items missing from a returned feed. Search ranking, completeness and cross-locale article identity are controlled by the source.

### Choose settings for your workflow

| Workflow | Start with | Useful fields | Next step in your system |
|---|---|---|---|
| Brand news monitoring | One company name, five results | `title`, `publisherName`, `publishedAt` | Review relevance before sending alerts |
| Competitive intelligence | Separate brand queries and a per-query cap | `query`, `matchedQueries`, `articleId` | Group coverage by brand and publisher |
| Industry news research | A focused topic and an appropriate locale | `snippet`, `googleNewsUrl`, `publishedAt` | Open the source before making claims |
| Regional news discovery | Local-language phrase, `language`, `country` | Locale fields and publisher metadata | Check that the source covers your region |
| AI research assistant | A small JSON input and explicit row budget | All structured fields plus diagnostics | Cite the returned link and verify the article |
| Spreadsheet reporting | A bounded batch, exported as CSV | Headline, publisher, UTC date and link | Deduplicate imported rows by `articleId` |

This Google News scraper retrieves metadata from public RSS search feeds. It suits news discovery and lightweight monitoring when a current snapshot is sufficient. The actor does not perform sentiment analysis, verify claims or decide whether an article is relevant to your business.

#### Monitor repeatedly without repeated alerts

Schedule runs in your Apify account or invoke the API from your automation platform. Keep a destination table keyed by `articleId`. On the first run, save a baseline; on later runs, alert only on IDs your destination has not seen. Store the article's `publishedAt` separately from `collectedAt` so an older story appearing in a new snapshot is not mistaken for a newly published story.

This workflow requires state in your own database, spreadsheet or automation. The actor itself does not persist a seen set between runs. Retrieving the same article again produces another delivered result and another article event. Google may assign different article URLs to related coverage, so deduplication is not semantic story clustering.

#### Map results into a spreadsheet

Use `title` as the headline column, `publisherName` as the source, `publishedAt` as the publication timestamp and `googleNewsUrl` as the article link. Keep `articleId` in an additional column for deduplication and `query` for attribution. Exporting the Dataset does not add a separate actor event; platform storage or transfer charges can still apply.

Do not use `publisherUrl` for the article-link column: it is a publisher homepage. Preserve `null` values so downstream users can distinguish a missing value from an empty string or a fabricated URL.

### A simple form for the first run

1. Choose **Search by company or topic phrase** and enter a phrase, or choose **Browse Google News categories** and select categories.
2. Keep **How many articles do you need?** at five and run.
3. Optionally open **Language, country and freshness** to select readable language/country names, a rolling period or newest-first order.
4. Leave **Exact dates and collection controls** unchanged unless you need a specific UTC window or network limits.

Language and country selectors suggest common editions while accepting custom codes. Existing API calls with `language` and `country` remain compatible.

### Every input setting

| Field | Default | Meaning and limits |
|---|---|---|
| `queries` | Required in search mode | Array of 1–20 search phrases, 1–300 characters each. Exact duplicate phrases are trimmed and removed. Queries are processed in order. |
| `maxResults` | `5` | Maximum unique article rows across the run, 1–1,000. Later queries are skipped once this cap is reached. This cap does not guarantee that many results. |
| `timeRange` | `"any"` | `any`, `24h`, `7d` or `30d`. Requests a recent feed and applies a rolling UTC lower boundary locally. Intersects exact dates. Not historical pagination. |
| `sortBy` | `"relevance"` | Source order or `"newest"`. Newest sorts each feed before caps and then the selected rows; query order still affects allocation. Unknown dates go last. |
| `language` | `"en"` | Language code, for example `en`, `fr` or `zh-Hans`. A syntactically valid locale may still have limited source coverage. |
| `country` | `"US"` | Uppercase two-letter country code, for example `US`, `FR` or `GB`. |
| `publishedAfter` | Unset | Inclusive publication boundary: ISO date or datetime. A date means midnight UTC; a datetime without an offset is interpreted as UTC. |
| `publishedBefore` | Unset | Exclusive publication boundary, with the same format. Must follow `publishedAfter`. |
| `maxArticlesPerQuery` | `100` | Maximum matching candidates examined per query after date filtering, 1–1,000 across all its feeds. Candidates already seen in another query count toward this cap. |
| `timeout` | `20` | HTTP timeout per attempt, 5–45 seconds. This is separate from the total Apify run timeout. |
| `maxRetries` | `1` | Retries per feed for transient network failures, HTTP 429 and selected server errors; 0–2. Backoff is bounded. |
| `mode` | `"search"` | `search` for phrases or `topics` for native category feeds. |
| `topics` | `["TECHNOLOGY"]` | 1–8 native category codes, used in topics mode. Search phrases are ignored in this mode. |
| `searchMode` | `"snapshot"` | `snapshot` or `daily`; daily is available only for keyword search. |
| `daysBack` | `7` | 1–31 days back from the exact end or now when no exact start is supplied. |
| `maxFeedRequests` | `20` | Global RSS fetch cap, 1–60, excluding retries and optional article requests. |
| `resolvePublisherUrls` | `false` | Attempt direct publisher article URLs for the selected enrichment rows. |
| `includeFullText` | `false` | Also resolves URLs and attempts public-page main-text extraction. |
| `maxEnrichedArticles` | `5` | Enrich only the first 1–100 selected rows; remaining rows are explicitly skipped. |
| `maxTextCharacters` | `20000` | Saved text cap per article, 1,000–100,000 characters. |

Only the query and total limit are needed in default search mode. Other settings are optional.

To give every query a chance, choose a larger global cap or make separate runs.

### Useful examples

#### Newest headlines from the last 24 hours

```json
{
  "queries": ["OpenAI"],
  "maxResults": 5,
  "timeRange": "24h",
  "sortBy": "newest"
}
```

The period is relative to the run start. It requests recency from Google and checks each publication timestamp locally; it does not promise complete coverage. With multiple queries, early queries can still consume the global cap. For historical dates, keep `timeRange` at `any` and use the exact date boundaries.

#### Compare two company searches

```json
{
  "queries": ["OpenAI", "Anthropic"],
  "maxResults": 10,
  "maxArticlesPerQuery": 5
}
```

#### Find French technology headlines

```json
{
  "queries": ["intelligence artificielle"],
  "language": "fr",
  "country": "FR",
  "maxResults": 5
}
```

#### Filter a returned snapshot by date

```json
{
  "queries": ["renewable energy"],
  "publishedAfter": "2026-10-01",
  "publishedBefore": "2026-11-01",
  "maxResults": 10
}
```

Replace these example dates with your desired period. An old period may return no matches because RSS is not a historical archive. For repeat monitoring, schedule runs in Apify and deduplicate `articleId` in your destination; this actor does not persist a cross-run seen set.

#### Three-topic research batch

```json
{
  "queries": ["battery recycling", "grid storage", "solar manufacturing"],
  "language": "en",
  "country": "GB",
  "maxResults": 15,
  "maxArticlesPerQuery": 5
}
```

The per-query cap gives later queries a chance before the global cap is filled. It does not guarantee five new articles per topic: overlap, date filters and source availability can reduce the result count.

### Output fields and link provenance

| Field | Description |
|---|---|
| `recordType` | Always `article`; diagnostic rows are never added to the Dataset |
| `articleId` | SHA-256 of the Google News article URL path; stable across tracking-query changes |
| `googleNewsId` | Source RSS GUID when present |
| `title` | Headline with an exact trailing publisher suffix removed when identified |
| `rawTitle` | Original headline text from the feed |
| `googleNewsUrl` | Google News article or RSS redirect URL |
| `publisherName` | Publisher named by the feed, or `null` |
| `publisherUrl` | Publisher homepage supplied by the feed, or `null` |
| `publisherArticleUrl` | Direct publisher article URL when resolution succeeds; otherwise `null`. Distinct from publisher homepage. |
| `publishedAt` | Parsed publication time in UTC, or `null` if unparseable |
| `publishedAtRaw` | Original publication date string when available |
| `snippet` | Plain text extracted from the RSS description; may repeat a headline or aggregate related links |
| `query` | First processed query that produced the article |
| `matchedQueries` | Queries in the processed snapshot in which this article was observed; not an exhaustive list of all possible matches |
| `language`, `country` | Requested locale, not independently detected article language/location |
| `collectedAt` | Time this run started collection, not the article publication time |
| `linkType`, `dataSource` | `google-news-redirect` and `google-news-rss` |

`publisherUrl` is a homepage. `googleNewsUrl` remains the original redirect even when `publisherArticleUrl` is resolved. Optional text extraction fetches public publisher HTML and may expose author/image metadata when present; it does not bypass login or paywalls. Different Google News URLs for the same story can remain separate rows.

### Precise configuration for AI agents

Use the input keys exactly as documented. `queries` is an array of strings, not a URL list; `maxResults` is a global result cap, not a page size. Start with five results, inspect the schema and diagnostics, then increase limits for the actual research task. Use `resolvePublisherUrls` or `includeFullText` only when needed and check each row's status. `includeFullText` also enables link resolution. Optional work is bounded by `maxEnrichedArticles`.

For a multi-query request, decide whether query order matters. An early query can consume the global cap, leaving later queries unprocessed. Use a small `maxArticlesPerQuery`, a larger global cap or separate calls when you need a clearer per-topic allocation. `matchedQueries` records observed matches among processed queries, not all searches that could match an article.

Treat `publishedAfter` as inclusive and `publishedBefore` as exclusive. For one UTC calendar day, use the start of that day and the next day as boundaries. The filter is applied to the returned RSS snapshot and cannot turn the source into a historical archive. If a requested date range is empty, report the bounded search outcome rather than claiming no such news exists.

Before consuming a run automatically, inspect its terminal status, `SUMMARY` and `ERRORS`. A row is research metadata, not a verified fact or permission to reproduce the article. Use `googleNewsUrl` for source inspection; do not construct a direct publisher URL from the homepage or headline.

### Diagnostics, limits and failures

- `SUMMARY.status` is `SUCCEEDED`, `PARTIAL` or `FAILED`. It includes per-query source counts, skipped queries, global limits and the number of delivered rows.
- `fullSearchCoverage` is always `false`. A successful run proves that a bounded feed was processed, not that every matching news article was collected.
- A valid empty feed or date-filtered empty result is a successful run with zero article rows. HTML, blocked requests, malformed XML and invalid article rows are recorded as errors.
- If one feed fails after another returns useful rows, the useful rows remain available and the run fails with partial-result diagnostics. Check `ERRORS` before consuming a batch automatically.
- Unknown dates remain `null`; rows with unknown dates are excluded when a date boundary is active.
- A delivery budget limit is reported separately in `SUMMARY.deliveryLimited`. Do not use a run status alone to infer complete delivery.

### Pricing by Apify tier

One useful article delivered to the default Dataset is one `apify-default-dataset-item` event. Your Apify pricing tier determines the rate; collecting more rows does not automatically unlock a different tier.

| Apify pricing tier | Per article | Per 1,000 delivered articles | Reduction from FREE rate |
|---|---:|---:|---:|
| FREE | $0.00050 | $0.50 | — |
| BRONZE | $0.00045 | $0.45 | 10% |
| SILVER | $0.00040 | $0.40 | 20% |
| GOLD | $0.00035 | $0.35 | 30% |
| PLATINUM / DIAMOND | $0.00035 | $0.35 | 30% |

These are Apify billing tier identifiers. Check the Pricing tab for the tier applied to your account. Enterprise tiers currently use the same article rate as GOLD.

There is **no start fee** and no extra actor event for queries, deduplication, locale selection or date filtering. Duplicates removed within a run, diagnostics and empty results create no article events. Articles collected again in a later run are new delivered results and are charged again.

| Delivered articles | FREE article events | GOLD article events | Additional cost |
|---|---:|---:|---|
| 0 | $0 | $0 | Platform usage for the attempted run |
| 5 | $0.00250 | $0.00175 | Platform usage |
| 100 | $0.050 | $0.035 | Platform usage |
| 1,000 | $0.50 | $0.35 | Platform usage |
| 10,000 across runs | $5.00 | $3.50 | Platform usage across runs |

The examples are arithmetic, not promises of source coverage. Each feed provides a bounded snapshot; daily mode can merge several feeds. A single run returns at most 1,000 rows.

Apify compute, storage, transfer and applicable platform services are paid by the user at the user's plan rates. No residential proxy or external service key is required. See each run's usage for the total. Set both a maximum total charge and a sensible run timeout; a result charge cap is not a universal cap on platform usage. When a delivery budget stops output, inspect `SUMMARY.deliveryLimited` before using the results.

### Browse native Google News categories

Select **Browse Google News categories**, then choose World, Nation, Business, Technology, Entertainment, Sports, Science or Health. These requests use Google News RSS topic sections rather than keyword searches named after categories. Country/language choose the edition; Nation is edition-specific. Query strings are ignored in this mode.

```json
{
  "mode": "topics",
  "topics": ["TECHNOLOGY", "SCIENCE"],
  "maxResults": 10,
  "maxArticlesPerQuery": 5
}
```

Rows carry `topic` and `matchedTopics`; `query` is `null` and `matchedQueries` is empty for a category result. Overlapping category URLs are deduplicated within the run. Limits and rolling/exact publication filters still apply. Category feeds cannot be swept day-by-day by this version.

### Search separate days

Daily mode sends distinct date-restricted RSS requests, newest day first. It applies each window's UTC boundaries locally, combines useful results and removes duplicate article IDs. It can discover articles absent from one current snapshot; it does not expose a next-page cursor or prove full historical coverage.

```json
{
  "queries": ["OpenAI"],
  "searchMode": "daily",
  "daysBack": 3,
  "maxFeedRequests": 4,
  "maxArticlesPerQuery": 250,
  "maxResults": 50
}
```

With an exact start/end, daily mode uses that interval instead of the automatic start. The interval is limited to 31 elapsed days, which can span 32 partial calendar days. `timeRange` intersects the exact dates; choose `any` for a historical interval. An explicit start more than 31 days before the end is rejected before collection.

`maxFeedRequests` caps the entire run's RSS fetches; retries do not count as new windows, but use network resources. Inspect `SUMMARY.feedRequests`, `requestLimitReached` and each feed's `sourceUrl`, `windowStart`, `windowEnd` and status. A global row cap or per-query candidate cap can stop collection before all windows or later queries are attempted. Source omissions remain possible even when every planned window is attempted.

### Direct publisher links and article text

```json
{
  "queries": ["site:science.nasa.gov Webb"],
  "maxResults": 3,
  "includeFullText": true,
  "maxEnrichedArticles": 3,
  "maxTextCharacters": 20000
}
```

For links only, set `resolvePublisherUrls: true` and leave `includeFullText` off. For text, one checkbox enables both resolution and public-page reading. The actor uses Google News decoding requests, then fetches publisher HTML for the selected rows. No external API key or residential proxy configuration is required. Google rate limits and publisher blocks can still prevent success.

`publisherUrlStatus` is `not_requested`, `resolved`, `unresolved` or `skipped_limit`. An unavailable direct URL stays `null`; the actor does not substitute the publisher homepage. `linkType` continues to describe `googleNewsUrl`, so it remains `google-news-redirect`.

`fullTextStatus` is `not_requested`, `extracted`, `url_unresolved`, `skipped_limit`, `fetch_failed`, `insufficient_text`, `blocked_page` or `paywall_detected`. Extracted text is the main readable content found in the fetched public HTML, not a guarantee of the complete original article. Detected structured paywalls are skipped; login, anti-bot pages, non-HTML responses and insufficient text are not returned as successful article bodies.

| Additional output | Meaning |
|---|---|
| `topic`, `matchedTopics` | Native topic provenance, or `null` / empty array for keyword rows |
| `publisherUrlStatus` | Whether direct article resolution was attempted and succeeded |
| `fullText`, `fullTextStatus` | Extracted main text or `null`, plus an explicit status |
| `fullTextTruncated` | Whether extracted text was clipped at your saved-character cap |
| `extractedTextCharacters` | Saved character count; zero when no text was extracted |
| `articleFetchUrl` | Final publisher-page URL used for successful extraction |
| `author`, `articleImageUrl` | Optional publisher metadata; `null` when unavailable. Images are not downloaded. |

`SUMMARY.publisherUrlsResolved`, `fullTextsExtracted`, `enrichmentWarnings`, `enrichmentLimited` and `enrichmentComplete` describe optional-work outcomes. Useful metadata remains delivered if optional enrichment fails; the run can succeed with unresolved links or missing bodies. Check these diagnostics instead of equating a successful metadata run with successful text extraction for every row.

There is no additional actor event for resolution, daily searches or text: one delivered useful metadata row remains one article event. These modes make more network requests, take longer and increase platform usage paid by the user. Start with 1–3 enriched articles and a suitable total runtime. A zero-result event bill can still have platform costs. Large enrichment batches may exceed a short overall run timeout before output is delivered.

### API, Python and workflow automation

Use the exact identifier **`apivault_labs/google-news-search`**, or Actor ID **`IWr1Q1aTT3WUatVOl`**. The JSON inputs above are also the contract for automation agents. Use an Apify API token from your own account and keep it in an environment variable or workflow credential.

#### Python with the official Apify client

Install `apify-client` version 3.3 or later and set `APIFY_TOKEN` in your environment:

```python
import os
from datetime import timedelta
from decimal import Decimal
from apify_client import ApifyClient

client = ApifyClient(os.environ["APIFY_TOKEN"])
run = client.actor("apivault_labs/google-news-search").call(
    run_input={"queries": ["OpenAI"], "maxResults": 5},
    max_total_charge_usd=Decimal("0.02"),
    run_timeout=timedelta(seconds=120),
)
if run is None or run.status != "SUCCEEDED":
    raise RuntimeError("Run incomplete; inspect its SUMMARY and ERRORS records")
store = client.key_value_store(run.default_key_value_store_id)
summary_record = store.get_record("SUMMARY")
errors_record = store.get_record("ERRORS")
if summary_record is None or errors_record is None:
    raise RuntimeError("Missing diagnostics")
summary, errors = summary_record["value"], errors_record["value"]
if errors or summary["status"] != "SUCCEEDED":
    raise RuntimeError("Incomplete delivery; inspect SUMMARY and ERRORS")
for article in client.dataset(run.default_dataset_id).iterate_items():
    print(article["title"], article["googleNewsUrl"])
```

A successful run can still hit a global or delivery limit. Read `SUMMARY` and `ERRORS` from the run's default key-value store before treating the result as complete. See [official Python client documentation](https://docs.apify.com/api/client/python/) and the Actor's API tab for other languages and exact endpoints.

#### HTTP, n8n, Make and custom agents

1. Send a JSON POST to `https://api.apify.com/v2/acts/apivault_labs~google-news-search/runs?memory=256&timeout=120&maxTotalChargeUsd=0.02` with header `Authorization: Bearer YOUR_APIFY_TOKEN` and `Content-Type: application/json`.
2. Save the returned run ID. Poll `GET https://api.apify.com/v2/actor-runs/RUN_ID` until a terminal state, or use an Apify run-finished webhook.
3. Read `SUMMARY` and `ERRORS` through `https://api.apify.com/v2/key-value-stores/STORE_ID/records/SUMMARY` and the equivalent `/ERRORS` endpoint. Read article rows from `https://api.apify.com/v2/datasets/DATASET_ID/items?clean=true`.

In n8n, these are standard HTTP Request nodes with stored header credentials. See [Apify API documentation](https://docs.apify.com/api/v2). A purpose-built verified n8n node, custom PyPI package and dedicated MCP server are not provided with this version. For MCP clients that expose Apify actors, pass this exact Actor ID and schema, then inspect the diagnostics just as an HTTP client does. No public preconfigured Tasks have been created in this pass.

### FAQ

**Can I get direct publisher URLs or full text?** Enable `resolvePublisherUrls` or `includeFullText`. Both are best effort and capped independently of metadata rows. Check `publisherUrlStatus`, `fullTextStatus` and `SUMMARY.enrichmentWarnings`; unavailable fields stay `null`.

**Why did a later query return no rows?** Inspect `SUMMARY.feeds`. The global cap may have skipped the query; its results may also be duplicates or excluded by your date window.

**Can this search all articles published last year?** No. Daily mode accepts a bounded range of up to 31 elapsed days and may return historical results Google still exposes, but does not guarantee archival completeness. Source/request/result limits still apply.

**Can an AI agent choose precise settings?** Yes: use the complete parameter table, keep `maxResults` small first, and read both `SUMMARY` and `ERRORS`. Missing data is `null`; a source failure is not a successful empty result.

**Does the country filter prove where an event happened?** No. `language` and `country` select the requested Google News edition. They are not detected article attributes or a geolocation classifier.

**Why is my snippet short or similar to the headline?** RSS descriptions vary by source and can contain related links. The actor extracts plain text from that description; it does not download the publisher's full article.

**Can I collect 10,000 stories in one run?** The input cap is 1,000 rows per run and the source is bounded per query. Multiple runs may overlap and do not establish exhaustive coverage. Price examples for 10,000 rows describe arithmetic across runs.

**Does a higher Apify tier change the data?** The listed tier changes the article-event price. The actor's search inputs, output fields and source coverage are the same.

**What should I check when fewer rows arrive than requested?** First inspect skipped queries, per-query limits, date filters, duplicates, source errors and `deliveryLimited` in the diagnostics. Increasing a cap cannot create results absent from the returned feed.

**How should I choose a query?** Begin with a specific company or topic phrase. Inspect five results for relevance, then refine the phrase or locale. Search interpretation and ranking come from Google; this actor does not guarantee a particular rank or keyword matching rule.

# Changelog

This Actor's version history is a separate document: https://apify.com/apivault_labs/google-news-search/changelog.md

# Actor input Schema

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

Search uses your phrases. Browse categories reads the real category feeds and ignores search phrases.

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

For keyword search: enter 1–20 phrases, one per line. Ignored in Browse categories mode. Search operators follow Google; they are not a matching guarantee.

## `maxResults` (type: `integer`):

Total unique articles for this run, not per query. Start with 5; article events cost at most $0.0025 at the listed rates, plus platform usage. Later queries may be skipped when the total cap is reached.

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

Used only in Browse categories mode. These are real Google News topic feeds, not keyword searches.

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

Requested Google News language, for example en, fr or zh-Hans. This is a locale request, not language detection on each article. Unsupported source combinations can return empty or fail.

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

Uppercase two-letter country edition, e.g. US, GB, FR. Does not prove that each publisher or event is located in that country.

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

Requests a recent feed and checks publication timestamps locally. This is a rolling UTC window ending at run start, not a complete archive. Exact date filters intersect this range; use Any date for historical dates.

## `sortBy` (type: `string`):

Newest first sorts each returned feed before its cap and then sorts the selected rows across queries. Queries are still processed in order; this is not a global ranking or an exhaustive archive. Unknown dates go last.

## `resolvePublisherUrls` (type: `boolean`):

Optional extra network work for the first maxEnrichedArticles rows. Unresolved URLs stay null with an explicit status. No extra actor event; platform usage increases.

## `includeFullText` (type: `boolean`):

Also enables direct-link resolution. Attempts main-text extraction from public publisher HTML; no paywall bypass. Check fullTextStatus and enrichmentWarnings; success and full original length are not guaranteed.

## `maxEnrichedArticles` (type: `integer`):

Limits optional URL/text work to the first selected output rows, independently of maxResults. Remaining rows report skipped_limit.

## `maxTextCharacters` (type: `integer`):

Limits saved main text. fullTextTruncated identifies clipping. It does not measure the original article length.

## `searchMode` (type: `string`):

Daily is for keyword searches only. Reads separate date-restricted feeds, deduplicates rows and applies exact UTC windows. It is not an exhaustive archive.

## `daysBack` (type: `integer`):

Daily mode only. Counts back from publishedBefore or now. Explicit publishedAfter replaces this start; relative timeRange intersects the dates. At most 31 elapsed days, possibly 32 partial calendar windows.

## `maxFeedRequests` (type: `integer`):

Global cap on feed fetches, excluding retries and optional article requests. Unattempted windows/queries appear in SUMMARY.feeds. Use a suitable overall run timeout.

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

Optional ISO date or datetime, inclusive. A date without a time means UTC midnight. Items with missing/unparseable publication dates cannot satisfy an active date filter.

## `publishedBefore` (type: `string`):

Optional ISO date or datetime, exclusive. Use the following day's midnight to include the whole preceding day. Must be later than publishedAfter.

## `maxArticlesPerQuery` (type: `integer`):

Maximum matching candidates per query across all its feeds, before deduplication; 1–1000. Each RSS feed remains bounded to about 100 entries.

## `timeout` (type: `integer`):

Per-feed request timeout; set the overall Actor runtime and spend cap separately in Console or your client.

## `maxRetries` (type: `integer`):

0 disables retries. At most two extra attempts for 429, selected 5xx and network errors, with bounded backoff. Other HTTP failures stop that feed.

## Actor input object example

```json
{
  "mode": "search",
  "queries": [
    "OpenAI"
  ],
  "maxResults": 5,
  "topics": [
    "TECHNOLOGY"
  ],
  "language": "en",
  "country": "US",
  "timeRange": "any",
  "sortBy": "relevance",
  "resolvePublisherUrls": false,
  "includeFullText": false,
  "maxEnrichedArticles": 5,
  "maxTextCharacters": 20000,
  "searchMode": "snapshot",
  "daysBack": 7,
  "maxFeedRequests": 20,
  "publishedAfter": "",
  "publishedBefore": "",
  "maxArticlesPerQuery": 100,
  "timeout": 20,
  "maxRetries": 1
}
```

# Actor output Schema

## `articles` (type: `string`):

No description

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

No description

## `errors` (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"
    ],
    "maxResults": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("apivault_labs/google-news-search").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"],
    "maxResults": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("apivault_labs/google-news-search").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"
  ],
  "maxResults": 5
}' |
apify call apivault_labs/google-news-search --silent --output-dataset

```

## MCP server setup

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

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/IWr1Q1aTT3WUatVOl/builds/WrB4a62itT14HBNKU/openapi.json
