Google News Scraper By Publisher & Site Filter avatar

Google News Scraper By Publisher & Site Filter

Pricing

$19.99/month + usage

Go to Apify Store
Google News Scraper By Publisher & Site Filter

Google News Scraper By Publisher & Site Filter

Scrape Google News results in real time for any topic, keyword, or region. Collect headlines, publishers, timestamps, article summaries, and links. Ideal for monitoring trends, tracking competitors, and gathering research data. Export clean structured output in JSON, CSV, or Excel.

Pricing

$19.99/month + usage

Rating

5.0

(3)

Developer

Scraper Engine

Scraper Engine

Maintained by Community

Actor stats

0

Bookmarked

72

Total users

2

Monthly active users

13 days ago

Last modified

Share

Google News Scraper — Publisher Domain, Headline and Publish Date

Google News Scraper By Publisher & Site Filter searches Google News and returns every article as structured JSON: the headline, the exact publisher domain taken from the feed's own source element, which of your target sites it matched, an ISO 8601 publish timestamp, the article's age in hours, and the literal query string that produced the row. Scope a search to reuters.com and bbc.com, exclude the outlets you do not want, and get a date window that is enforced twice. Both required inputs are prefilled — open it and press Start.

⚠️ Read the constraints section below before your first run. The link field is a news.google.com redirect, not the publisher's own article URL; snippet is a short capped description, never the article body; and one Google News request returns roughly 100 articles.

What is Google News Scraper By Publisher & Site Filter?

Google News Scraper By Publisher & Site Filter is an Apify Actor that reads the public Google News RSS feeds — keyword search, top stories, topic sections, city feeds and hashed topic ids — and shapes each <item> into one flat, typed dataset row. The publisher filter works in two places at once: your target domains are folded into the query as site: operators, and every returned row is then re-checked against its real publisher domain before anything is stored.

No Google account, login, cookie or API key is involved, and there is no Google News API key to obtain because Google does not publish one. The only credential in play is your Apify token, and by default requests go out with no proxy at all.

It is built for media monitoring and PR teams tracking named outlets, market and competitive analysts building dated coverage datasets, and developers feeding headline streams into dashboards, alerting jobs or agent tools.

What Google News article data is publicly available to scrape?

The Google News RSS surface publishes, to any anonymous request, a headline, a publish timestamp, a short description, an article id and a <source> element carrying the publisher's name and homepage URL. What it does not publish is the thing most people assume it does: the publisher's own article URL. Everything past the headline lives on the publisher's site.

Data CategoryGoogle News RSS feedOn the publisher's own site
Headline text✅ Public
Publisher name and homepage URL✅ Public — the feed's <source> element
Publish timestamp✅ Public — RFC 822, GMT
Stable per-article id✅ Public — the RSS guid
Article link✅ Public — but only as a news.google.com/rss/articles/... redirectThe real article URL is on the publisher's page
Description snippet✅ Public — short, and capped at 200 characters hereFull standfirst / summary
Full article body textBehind the publisher's page, often a paywall or registration wall
Author bylineOn the publisher's article page — not in the feed at all
Per-article imageSee the note below — this surface does not give a usable per-article image
Comments, share counts, paywall statusPublisher-side only

Google News Scraper By Publisher & Site Filter only returns publicly visible data — what any anonymous request to the public RSS feed receives. Nothing behind a login wall.

⚠️ Google redirect links, snippet-only text, and a ~100-article cap

Four things about this Actor are worth knowing before you wire it into anything, so they get their own section instead of a footnote in a table.

Links stay as Google redirects. They are not resolved. link and rssLink both come back as https://news.google.com/rss/articles/CBMi... redirect URLs. This Actor does not decode them into the publisher's own article URL, and there is no toggle that makes it. The only publisher-side URL you get is publisherHomeUrl / sourceUrl, and that is the outlet's homepagehttps://www.reuters.com, not the article. If your pipeline needs a fetchable article URL, this Actor cannot give it to you, and the competitor comparison in the FAQ names two listings that document resolving them.

You get a snippet, never the article body. snippet is the RSS <description> with HTML tags stripped, entities unescaped, and the result truncated to 200 characters followed by .... Because the search feed's description is usually just an anchor tag wrapping the headline plus the outlet name, the snippet frequently reduces to roughly the headline again. The Actor never requests the publisher's page, so there is no full text, no standfirst and no body extraction anywhere in it.

One Google News request returns about 100 articles, and there is no pagination. That ceiling is Google's, not the Actor's: independent queries measured 97, 100, 102, 105, 106 and 107 items on 2026-07-23, and num, start, count and scoring are all ignored on this surface. Setting maxItems to 500 without deepCoverage returns roughly 100 rows and logs a warning telling you so. deepCoverage is the way past it — it re-runs the same query across several time shards and merges by article id.

No per-article image is emitted. The Actor parses a media URL out of the feed when one is present but does not write it to the dataset, and thumbnail is always an empty string. The reason is recorded in the source: an earlier build fetched link and inlined its Open Graph image, and on a live run across five different publishers every resulting thumbnail was byte-identical — it was the generic Google News interstitial image, not the article's. The field was emptied rather than shipped as a fabricated picture repeated on every row.

What data can I extract with Google News Scraper By Publisher & Site Filter?

Every row carries the article, its publisher, several views of its publish time, and the full provenance of how it was produced — which query string, which time filter, which feed, which shard. Twenty-eight keys on every row, always the same twenty-eight; the default dataset view shows fifteen of them, so the rest are in the JSON and the CSV export but not in that table view.

Field NameDescription
position1-based index within the final, already-filtered result list. Renumbered after the publisher and date filters run, so it is always contiguous
titleThe headline, with the trailing - Publisher suffix that Google News appends split off into source
linkA news.google.com/rss/articles/... redirect URL, not the publisher's article URL. Taken from the first <a href> in the description when there is one, otherwise from the item's <link>. Both forms are Google redirects
domainLegacy heuristic field kept for output parity with the base Actor: a 13-entry hardcoded outlet-name lookup, falling back to the host of link — which is news.google.com. Use publisherDomain instead
sourcePublisher name as split off the end of the headline, e.g. Reuters. Empty string when the headline had no - suffix
dateRelative English prose computed against the moment the run executed: Just now, 41 minutes ago, 3 hours ago, 2 days ago, 5 months ago. Falls back to the raw pubDate string when it cannot be parsed
date_utcISO 8601 UTC timestamp, identical in value to publishedAt. null when the feed's pubDate did not parse. Snake_case, kept from the base Actor
snippetRSS description with HTML stripped and entities unescaped, truncated to 200 characters plus .... Not the article body
thumbnailAlways an empty string — see the constraints section above
block_positionIdentical in value to position. Kept from the base Actor's output contract
queryThe raw query input echoed back, unmodified — the keyword alone, without any of the operators
guidThe RSS guid, the stable per-article id. This is the key deduplication runs on across shard requests. null if the feed omitted it
publisherDomainThe real publisher domain, parsed from the feed's own <source url="..."> element and lowercased with www. stripped, e.g. theverge.com. null when the feed omitted the source element. This is the field to group and filter on
publisherNamePublisher name from the <source> element's own text, falling back to source. null if neither is present
publisherHomeUrlThe publisher's homepage URL exactly as the feed gives it, e.g. https://www.reuters.com. Not the article URL. null when absent
sourceUrlIdentical in value to publisherHomeUrl. Both keys are emitted so pipelines written against either naming convention keep working
matchedSiteWhich entry of your publisherSites list this row matched, e.g. bbc.com for an article on news.bbc.co.uk. null when publisherSites is empty or nothing matched
publishedAtISO 8601 UTC publish timestamp with an explicit +00:00 offset, parsed from the feed's RFC 822 pubDate. null when it did not parse
pubDateRawThe untouched pubDate string as the feed sent it, e.g. Sat, 25 Jul 2026 06:41:00 GMT. Keep it if you want to re-parse yourself
ageHoursHours between the article's publish time and the moment the run executed, rounded to 2 decimals. null when the date did not parse
ageDaysThe same figure in days, rounded to 2 decimals. null when ageHours is null
rssLinkThe item's own <link> value — the canonical Google News redirect for the article, ending in ?oc=5
loadedUrlThe Google News feed URL that produced this row, not the article URL. Note this differs from the same-named field in some other Google News Actors, where it holds the resolved article link
feedUrlIdentical in value to loadedUrl
appliedQueryThe literal q= string that was sent, operators and all, e.g. nvidia (site:reuters.com OR site:bbc.com) when:1d. Empty on non-search feed modes. Your audit trail for exactly what was asked
appliedTimeFilterThe time clause that was applied, e.g. when:1d or after:2026-07-01 before:2026-07-15. null when no date filter resolved
feedModeWhich feed produced this row: search, topStories, topic, geo or topicId
shardWindowWhich Deep Coverage shard this row came from — a window label like 6h, or a date-range label like 2026-07-01..2026-07-06. null on the primary request and whenever Deep Coverage is off

Field names are camelCase with two deliberate exceptions inherited from the base Actor: date_utc and block_position. The same split exists on the input side, where time_period, time_period_min, time_period_max, gl, hl, lr, cr, nfpr and filter are legacy keys sitting alongside camelCase names.

Article and publisher fields

publisherDomain and matchedSite are the two that make this Actor what it is. publisherDomain is not inferred from the redirect link or guessed from the outlet's name — it is read from the <source url="..."> attribute the feed itself publishes, then lowercased and stripped of www.. matchedSite tells you which entry of your own list it satisfied, and matching is suffix-aware, so news.bbc.co.uk matches a publisherSites entry of bbc.co.uk and www.bbc.com matches bbc.com. The legacy domain field is kept only so an existing pipeline does not break; on any outlet outside its 13-entry lookup table it returns news.google.com, which is why the examples below show both side by side.

Date, age and provenance fields

Three of the four date fields are absolute and one is not. publishedAt and date_utc are ISO 8601 with an explicit UTC offset, pubDateRaw is the feed's original RFC 822 string, and the timezone is always recoverable because the feed publishes GMT and the parser normalises everything to UTC. date is the odd one out: it is relative English prose computed at the moment the run executed, so it ages the instant it is written and is not safe to sort or join on. ageHours and ageDays are measured against the same run moment. For provenance, appliedQuery and appliedTimeFilter let you reconstruct precisely what was sent to Google for any row, and shardWindow tells you which Deep Coverage request found it.

🤖 Add-on: Need additional Google or news data?

Headlines tell you what was published; they do not tell you what people searched for or said about it. Google Search Autocomplete Scraper with YouTube Suggestions returns the suggestion tree for the same keyword, which is a useful demand signal next to a coverage count, and Google Maps Scraper with Reviews Sentiment Analysis covers the local-business side of the same brand. For the reaction to a story rather than the story itself, X Twitter Posts Search and Reddit Posts Scraper by Keyword & Score Filter take a headline straight out of the title field.

Why not build this yourself?

Google publishes no public News API for third parties, so there is no supported route to compare against — every option, including this one, reads the same public RSS surface. What makes it a maintenance job rather than an afternoon's work is that the surface fails in ways that return HTTP 200.

The date operators are the clearest example. The &tbs=qdr:* parameter that every Google Search tutorial reaches for is a proven no-op on Google News RSS. when: works, but only with hours, days and years — when:1w and when:1m return HTTP 200 with zero items, which reads as "no news this month" rather than as an error, so a naive build ships a silent empty-result bug. after: and before: work but are not absolute: measured on 2026-07-23, a compound query returned 98 of 100 rows in window and leaked two, one of them dated 2017, while when: leaked 0 of 144. Enforcing the window you advertised means re-checking every row after the fetch.

Then there is volume. One request is capped around 100 items and the surface has no pagination at all, so the only way past it is to shard the same query across several time windows and merge by article id — and the shards have to respect the recency the user actually asked for, or a 6-hour request quietly returns week-old articles. Locale is another: hl and gl genuinely change which outlets appear, but lr, cr, nfpr and filter are ignored outright, measured as a byte-identical feed, so a build that exposes them is selling four knobs that do nothing.

Add to that: the publisher domain is only trustworthy when read from the feed's <source url> element rather than inferred from the redirect link; a soft block arrives as a 200 carrying a consent wall rather than a 403, so the only safe signal is whether the body parsed as an RSS document at all; and per-article thumbnails from this surface are the same generic Google image on every row. None of that is visible until it is in production, and each fix costs a debugging session and a redeploy.

How to use Google News Scraper By Publisher & Site Filter

Google News Scraper By Publisher & Site Filter runs on Apify. Start it from the Apify Console or call it through the Apify API.

  1. Open the Actor on Apify and click Try for free
  2. Set Search Keyword (query) — one of the two required inputs, prefilled with Elon Musk
  3. Set Maximum Articles (maxItems) — the other required input, prefilled with 10, minimum 1, maximum 50000
  4. Add the outlets you care about to Publisher Sites (publisherSites), one domain per entry. Full URLs and www. prefixes are accepted and normalised, so https://www.BBC.com/news/ becomes bbc.com
  5. Optionally narrow further: Time Window for recency, Exact Phrase for a quoted match, Headline Only to force intitle:, Excluded Publisher Sites and Exclude Terms to subtract
  6. Click Start, then export as JSON, CSV, Excel or XML, or read the dataset through the Apify API

What happens if a required input is missing. Both query and maxItems declare defaults in the input schema, so the platform fills them in rather than rejecting the run — which means an API call that omits query does not fail, it runs a search for Elon Musk and charges you for those rows. An API call that omits maxItems returns 10 articles. There is one case where the Actor stops itself: if feedMode is search and query is present but empty and publisherSites and matchPhrase are both empty, it logs No search query provided., exits cleanly, and pushes nothing — a zero-row, zero-charge run rather than a crash.

How to scale past the ~100-article cap

One run covers one query, so bulk here means depth rather than breadth. Set maxItems above 100 and turn on Deep Coverage (deepCoverage): the Actor re-runs the identical query across a series of when: shards — 1h, 2h, 3h, 6h, 12h, 1d, 2d, 3d, 7d by default, editable via deepCoverageWindows — and merges the results by guid, so nothing is duplicated. If dateFrom and dateTo are both set, it splits that range into deepCoverageDateShards sub-ranges instead, 6 by default and clamped to between 2 and 30. Measured on 2026-07-23 and recorded in the Actor's own input schema: 296 unique articles against 106 from a single request, and a 30-day range split into 6 shards returning 577 unique against 100. Deep Coverage is skipped entirely when maxItems is 100 or below, since one request already covers it. For several keywords or several markets, run the Actor once per query — a schedule per query is the usual pattern.

What can you do with Google News article data?

  • 📰 A PR manager running a daily clipping report sets publisherSites to the client's twelve target outlets with strictSiteFilter on, then reports on publisherDomain, title and publishedAt — knowing every row in the dataset genuinely came from one of those twelve.
  • 📈 A competitive intelligence analyst tracks a rival with timeWindow: "1d" on a schedule and uses ageHours to separate a story breaking in the last three hours from yesterday's follow-ups, instead of re-reading date prose.
  • 🗺️ A market researcher comparing coverage across editions runs the same query once per gl value and groups on publisherDomain to see which outlets carry a story in the United States edition but not the United Kingdom one.
  • 🔍 An SEO strategist studying news visibility sets titleOnly: true and reads which publisherName values dominate headline matches for a keyword, using matchedSite to confirm the shortlist rather than eyeballing domains.
  • 🤖 An AI engineer building a news agent indexes title, snippet, publisherName and publishedAt into a vector store so the agent answers "what did Reuters publish about this yesterday" from observed rows instead of stale training data — and keeps appliedQuery as the provenance stamp on each chunk.
  • 🧾 A compliance or research team archiving coverage stores guid as the primary key and pubDateRaw alongside publishedAt, so the record keeps both the normalised timestamp and the exact string the feed emitted.

Every one of these is callable from an agent framework over the Apify API, since the Actor is a standard HTTP-triggered run.

How does Google News Scraper By Publisher & Site Filter handle rate limits and blocking?

Google News RSS answers this Actor without a proxy, and that is the default: proxyConfiguration prefills useApifyProxy: false and a plain run goes out on a direct connection. Requests carry a desktop Chrome user-agent and a 30-second timeout, and there is no headless browser, no JavaScript execution and no cookie jar anywhere in it.

Blocking is handled by escalation rather than by a captcha solver — there is no captcha solving in this Actor at all, because this surface does not put a challenge in front of these requests. If a request fails, the proxy tier steps up: direct connection, then an Apify datacenter proxy, then Apify residential, up to three attempts per feed URL with a 1-, 2-, then 3-second pause between them. A proxyConfiguration you set yourself is used on the first rung. Two status codes skip retrying because retrying cannot help: 400 and 404, which on this surface mean a malformed topicId or an unrecognised geoLocation, not a block.

The block test is deliberately narrow. A response counts as blocked only when the body does not parse as an RSS document at all — a consent wall, an interstitial or an HTTP error page. A feed that parses correctly and contains zero <item> elements is treated as empty, not blocked, because a loose "sorry" or "captcha" substring test would be a near-total false positive on a news feed. Between shard requests the Actor pauses 250 ms.

If every request in a run is blocked, the Actor logs Every feed request was blocked or returned an invalid document. and exits cleanly with an empty dataset. It does not push placeholder rows and it does not charge for the attempt.

⬇️ Input

Twenty-nine parameters read straight from the input schema, two of them required. They are shown as 24 rows below: the two date-bound pairs and the four legacy no-ops share an identical shape and are collapsed into one labelled row each.

ParameterRequiredTypeDescriptionExample Value
queryYesstringTopic or keyword to search Google News for. Combined with the publisher and date filters into a single query string, echoed back on every row as appliedQuery. Default "Elon Musk" — omitting it over the API runs that search rather than failing."semiconductor export controls"
maxItemsYesintegerHow many articles to store and charge for. Minimum 1, maximum 50000, default 10. A value below 1 is clamped up to 1 with a warning. One Google News request is capped near 100 items, so anything higher needs deepCoverage.50
publisherSitesNoarray of stringsOnly return articles from these outlets. Expanded into site:a or (site:a OR site:b) inside the query. Full URLs and www. prefixes are normalised. Default [], prefilled ["reuters.com", "bbc.com"]. Empty means all publishers.["reuters.com", "bbc.com"]
excludeSitesNoarray of stringsDrop articles from these outlets. Expanded into -site:x inside the query, then re-checked against each row's real publisher domain regardless of strictSiteFilter. Default [].["example-aggregator.com"]
strictSiteFilterNobooleanRe-check every row's real publisher domain, taken from the feed's own <source url> element, against publisherSites and drop anything off-list before it is stored or charged. Default true.true
matchPhraseNostringRequire this exact phrase; added to the query in quotes. Google matches it against the whole article, so it will not always appear in the headline. No default."export licence"
excludeTermsNoarray of stringsWords that must not appear. Each is added to the query as -term. Default [].["rumour", "opinion"]
titleOnlyNobooleanMatch query in the headline only, using intitle:. Applies to query alone, not to matchPhrase. Default false.false
timeWindowNostringRelative recency filter applied with the when: operator. Closed enum of 14 values: "" for no filter, plus 1h, 2h, 3h, 6h, 12h, 1d, 2d, 3d, 7d, 14d, 30d, 90d, 1y. Weeks and months are absent because when:1w and when:1m return zero items on this surface. Takes precedence over dateFrom/dateTo and over time_period."1d"
dateFrom / dateToNostringTwo parameters — the absolute lower and upper bound of the publish window. Both accept YYYY-MM-DD or MM/DD/YYYY and are applied as the after: and before: operators. Either can be used alone. Ignored whenever timeWindow is set. Neither has a default."2026-07-01"
strictDateFilterNobooleanRe-check every article's publish date against the requested window and drop anything outside it before it is stored or charged. Only active when feedMode is search and a time filter resolved. An article whose date could not be parsed is also dropped. Default true.true
deepCoverageNobooleanRun the same query across several time shards and merge by guid. Only engaged when maxItems is above 100 — below that it logs a note and is skipped. Default false.true
deepCoverageWindowsNoarray of stringsThe when: shards used when no date range is set. Digits plus h, d or y only; invalid entries are dropped, and if all are invalid the defaults are restored. Never shards wider than the timeWindow you asked for. Default ["1h","2h","3h","6h","12h","1d","2d","3d","7d"].["1h", "6h", "1d", "7d"]
deepCoverageDateShardsNointegerWhen dateFrom and dateTo are both set, Deep Coverage splits that range into this many sub-ranges instead of using the windows above. Minimum 2, maximum 30, default 6; out-of-range and unparseable values are clamped in code.6
feedModeNostringWhich Google News feed to read. Enum: search, topStories, topic, geo, topicId. Default "search". Only search supports query operators — on the other four the keyword, publisher, phrase and date operators are not applied to the request, and a warning is logged. An unknown value falls back to search."search"
topicNostringRead only when feedMode is topic. Enum of 8: WORLD, NATION, BUSINESS, TECHNOLOGY, ENTERTAINMENT, SPORTS, SCIENCE, HEALTH. Default "WORLD"; an unknown value falls back to WORLD with a warning."TECHNOLOGY"
geoLocationNostringRead only when feedMode is geo. A city or region name. Required in that mode — without it the run logs an error and exits cleanly. No default."Chicago"
topicIdNostringRead only when feedMode is topicId. The CAAq... id copied from a news.google.com topic URL. Required in that mode — without it the run exits cleanly. No default."CAAqJggKIiBDQkFTRWdvSUwyMHZNRGRqTVhZU0FtVnVHZ0pWVXlnQVAB"
glNostringGoogle News country edition. Genuinely honoured — it changes which outlets appear. Closed enum of 245 country names, not ISO codes; the code defaults to United States when unset. A value outside the table logs a warning and falls back to us, so passing "gb" gets you the United States edition."United Kingdom"
hlNostringGoogle News interface and result language. Genuinely honoured. Closed enum of 135 language names, not codes; the code defaults to English when unset. An unmapped value falls back to en silently, with no warning."German"
time_periodNostringLegacy input, kept so older run configurations keep working. Enum of 6: last_hour, last_day, last_week, last_month, last_year, custom. Now mapped onto the working when: and after:/before: operators instead of the &tbs=qdr: parameter Google News RSS ignores. timeWindow and dateFrom/dateTo both take precedence over it. No default."last_day"
time_period_min / time_period_maxNostringTwo parameters, read only when time_period is custom. MM/DD/YYYY, mapped to after: and before:. If neither parses, a warning is logged and no date filter is applied at all. Neither has a default."07/01/2026"
lr / cr / nfpr / filterNostring, string, integer, integerFour legacy parameters accepted for backwards compatibility and ignored by the Google News RSS surface — measured as a byte-identical feed in every case. lr is a 43-value language enum, cr a 245-value country enum, nfpr an integer 0–1 defaulting to 0, filter an integer 0–1 defaulting to 1. Setting any of them logs a warning naming the replacement: use hl instead of lr, gl instead of cr."English"
proxyConfigurationNoobjectProxy strategy, proxy editor. Prefilled {"useApifyProxy": false} — Google News RSS answers fine with no proxy. Your selection is used on the first attempt; on a genuine block the Actor escalates to an Apify datacenter proxy and then to residential regardless.{"useApifyProxy": false}

Precedence, in one line: timeWindow beats dateFrom/dateTo, which beat time_period. Only the winner appears in appliedTimeFilter.

Example input

A one-day sweep of three named outlets for a phrase, capped at 50 articles, with both purity gates on. All 29 parameters are shown; the legacy no-ops are included only to make the full surface visible.

{
"query": "semiconductor export controls",
"maxItems": 50,
"publisherSites": ["reuters.com", "bbc.com", "theverge.com"],
"excludeSites": ["example-aggregator.com"],
"strictSiteFilter": true,
"matchPhrase": "export licence",
"excludeTerms": ["rumour", "opinion"],
"titleOnly": false,
"timeWindow": "1d",
"dateFrom": "",
"dateTo": "",
"strictDateFilter": true,
"deepCoverage": false,
"deepCoverageWindows": ["1h", "2h", "3h", "6h", "12h", "1d", "2d", "3d", "7d"],
"deepCoverageDateShards": 6,
"feedMode": "search",
"topic": "TECHNOLOGY",
"geoLocation": "",
"topicId": "",
"gl": "United States",
"hl": "English",
"time_period": "",
"time_period_min": "",
"time_period_max": "",
"lr": "",
"cr": "",
"nfpr": 0,
"filter": 1,
"proxyConfiguration": { "useApifyProxy": false }
}

⬆️ Output

One dataset row per article, typed and normalized, with the same 28 keys on every row of every run — keys are always present, and a missing value comes back as null or an empty string rather than being omitted. Rows are pushed one at a time as they are built, so the dataset fills while the run is still going. Export as JSON, JSONL, CSV, Excel, HTML table or XML, or read the dataset through the Apify API.

Charging is per saved row: one row_result event per article stored. There are no error, diagnostic or accounting rows of any kind in this Actor — verified against the row builder, which writes exactly one shape and always with the charged event attached. There is no errorReason, no status, no isError and no row-type marker, so there is no filter expression to apply: every row in your dataset is a real article row and every one of them was charged. Failures never become rows. A blocked run, an empty feed, a missing geoLocation, an unusable topicId or a filter that removed everything all end the same way — a warning or error in the log and a clean exit with nothing pushed.

That design has one consequence worth planning for. The publisher and date gates run after the fetch and before the push, so off-list and out-of-window articles cost you nothing in charged events — but they do shrink the result. Asking for maxItems: 50 with a tight publisherSites list can legitimately return 12 rows, and the run log tells you exactly why, reporting how many rows were kept, how many were dropped by the publisher filters, and how many fell outside the date window.

Deduplication is by guid, falling back to rssLink, across every request in a run — so Deep Coverage shards that overlap contribute each article once. It is scoped to a single run and a single query; two runs of different queries can both return the same article, each with its own appliedQuery.

Example output

A row from a publisherSites: ["reuters.com", "bbc.com"] search with timeWindow: "1d", where the legacy domain heuristic happens to know the outlet:

{
"position": 1,
"title": "Chipmakers weigh impact of new export licence rules",
"link": "https://news.google.com/rss/articles/CBMiiAFBVV95cUxQUXh5WVZ2RkNpNG9ndjF6V3hMRHBRTGRSVnNkelpwZDY2TWJzejBSMGZrRC1rSm5DZ1BxanpoeFFGdDRjWGpZR0tOUG9FY0kyeWFXOE9MSzBobTg1ajRiZzVhSWhtbm5nSVNJVWExSDBSaEFjUUJkT1JRRDJHSDBrMU9jU2ZZN3RN?oc=5",
"domain": "reuters.com",
"source": "Reuters",
"date": "3 hours ago",
"date_utc": "2026-07-25T06:41:00+00:00",
"snippet": "Chipmakers weigh impact of new export licence rules Reuters",
"thumbnail": "",
"block_position": 1,
"query": "semiconductor export controls",
"guid": "CBMiiAFBVV95cUxQUXh5WVZ2RkNpNG9ndjF6V3hMRHBRTGRSVnNkelpwZDY2TWJzejBSMGZrRC1rSm5DZ1BxanpoeFFGdDRjWGpZR0tOUG9FY0kyeWFXOE9MSzBobTg1ajRiZzVhSWhtbm5nSVNJVWExSDBSaEFjUUJkT1JRRDJHSDBrMU9jU2ZZN3RN",
"publisherDomain": "reuters.com",
"publisherName": "Reuters",
"publisherHomeUrl": "https://www.reuters.com",
"sourceUrl": "https://www.reuters.com",
"matchedSite": "reuters.com",
"publishedAt": "2026-07-25T06:41:00+00:00",
"pubDateRaw": "Sat, 25 Jul 2026 06:41:00 GMT",
"ageHours": 3.12,
"ageDays": 0.13,
"rssLink": "https://news.google.com/rss/articles/CBMiiAFBVV95cUxQUXh5WVZ2RkNpNG9ndjF6V3hMRHBRTGRSVnNkelpwZDY2TWJzejBSMGZrRC1rSm5DZ1BxanpoeFFGdDRjWGpZR0tOUG9FY0kyeWFXOE9MSzBobTg1ajRiZzVhSWhtbm5nSVNJVWExSDBSaEFjUUJkT1JRRDJHSDBrMU9jU2ZZN3RN?oc=5",
"loadedUrl": "https://news.google.com/rss/search?q=semiconductor%20export%20controls%20%22export%20licence%22%20%28site%3Areuters.com%20OR%20site%3Abbc.com%29%20when%3A1d&hl=en&gl=us&ceid=US:en",
"feedUrl": "https://news.google.com/rss/search?q=semiconductor%20export%20controls%20%22export%20licence%22%20%28site%3Areuters.com%20OR%20site%3Abbc.com%29%20when%3A1d&hl=en&gl=us&ceid=US:en",
"appliedQuery": "semiconductor export controls \"export licence\" (site:reuters.com OR site:bbc.com) when:1d",
"appliedTimeFilter": "when:1d",
"feedMode": "search",
"shardWindow": null
}

And a row from an outlet the legacy heuristic does not know, which is what makes publisherDomain the field to trust. Note domain reporting news.google.com while publisherDomain reports the real outlet, and shardWindow populated because this row arrived from a Deep Coverage shard:

{
"position": 7,
"title": "Inside the fab: what the new licence regime changes",
"link": "https://news.google.com/rss/articles/CBMigAFBVV95cUxQRDJDNW1ONklDTlhJN3lsWlIwdTEzV050d284bnZ4YWo2TnQ3MU1XcUZkdHNZTTMxSTZ4NjkwRnh0UFloa0ZsZ0d5Qmx0NjRFd25qMXdBTmN6TVBmcHdKdXhGWnRCSDVMdjVJZlJkTlRTMjZSZXZwdGNYM28xbE9uTA?oc=5",
"domain": "news.google.com",
"source": "The Verge",
"date": "11 hours ago",
"date_utc": "2026-07-24T22:05:00+00:00",
"snippet": "Inside the fab: what the new licence regime changes The Verge",
"thumbnail": "",
"block_position": 7,
"query": "semiconductor export controls",
"guid": "CBMigAFBVV95cUxQRDJDNW1ONklDTlhJN3lsWlIwdTEzV050d284bnZ4YWo2TnQ3MU1XcUZkdHNZTTMxSTZ4NjkwRnh0UFloa0ZsZ0d5Qmx0NjRFd25qMXdBTmN6TVBmcHdKdXhGWnRCSDVMdjVJZlJkTlRTMjZSZXZwdGNYM28xbE9uTA",
"publisherDomain": "theverge.com",
"publisherName": "The Verge",
"publisherHomeUrl": "https://www.theverge.com",
"sourceUrl": "https://www.theverge.com",
"matchedSite": "theverge.com",
"publishedAt": "2026-07-24T22:05:00+00:00",
"pubDateRaw": "Fri, 24 Jul 2026 22:05:00 GMT",
"ageHours": 11.72,
"ageDays": 0.49,
"rssLink": "https://news.google.com/rss/articles/CBMigAFBVV95cUxQRDJDNW1ONklDTlhJN3lsWlIwdTEzV050d284bnZ4YWo2TnQ3MU1XcUZkdHNZTTMxSTZ4NjkwRnh0UFloa0ZsZ0d5Qmx0NjRFd25qMXdBTmN6TVBmcHdKdXhGWnRCSDVMdjVJZlJkTlRTMjZSZXZwdGNYM28xbE9uTA?oc=5",
"loadedUrl": "https://news.google.com/rss/search?q=semiconductor%20export%20controls%20%28site%3Areuters.com%20OR%20site%3Atheverge.com%29%20when%3A12h&hl=en&gl=us&ceid=US:en",
"feedUrl": "https://news.google.com/rss/search?q=semiconductor%20export%20controls%20%28site%3Areuters.com%20OR%20site%3Atheverge.com%29%20when%3A12h&hl=en&gl=us&ceid=US:en",
"appliedQuery": "semiconductor export controls (site:reuters.com OR site:theverge.com) when:12h",
"appliedTimeFilter": "when:1d",
"feedMode": "search",
"shardWindow": "12h"
}

How does it work?

The Actor assembles one literal query string from your inputs — the keyword, optionally wrapped in intitle:, plus a quoted matchPhrase, plus (site:a OR site:b) for your publisher list, plus -site:x and -term for the exclusions, plus the winning time clause — and issues a plain HTTP GET against the Google News search feed with your hl, gl and the derived ceid locale parameter. The other feed modes hit the top-stories, topic, geo or topic-id feed instead. There is no headless browser, no JavaScript execution, no login and no cookie jar. Requests go out directly by default and escalate through Apify datacenter and residential proxies only if a response fails to parse as RSS.

Each item is parsed for its headline, id, publish date, description and, crucially, the <source url> element carrying the publisher's real domain. Results from every request in a run are merged and deduplicated by guid, then passed through the publisher-purity and date-window gates before a single row is written — which is why a filtered-out article never reaches your dataset and never costs an event. Only publicly visible feed data is collected, and the 28 output key names stay the same whatever Google does to its own front end.

Integrations

Google News Scraper By Publisher & Site Filter is an Apify Actor, so it works with anything that can call the Apify API or consume a dataset.

Calling Google News Scraper By Publisher & Site Filter from Python

The callable Actor id is your username plus the Actor's slug:

from apify_client import ApifyClient
client = ApifyClient("<YOUR_APIFY_TOKEN>")
run = client.actor("<YOUR_USERNAME>/google-news-scraper-by-publisher-site-filter").call(run_input={
"query": "semiconductor export controls",
"maxItems": 50,
"publisherSites": ["reuters.com", "bbc.com"],
"strictSiteFilter": True,
"timeWindow": "1d",
})
for rec in client.dataset(run["defaultDatasetId"]).iterate_items():
print(rec["publishedAt"], rec["publisherDomain"], rec["title"], rec["link"])

Works in Go, Ruby, Node.js, cURL — any language that can make an HTTP request. Always pass query explicitly: leave it out and the schema default runs a search for Elon Musk.

No-code tools (n8n, Make, Zapier)

In n8n, use the Apify node — or an HTTP Request node pointed at the Apify run endpoint with your token — and pass the same JSON input shown above; a Filter node on publisherDomain or matchedSite narrows a multi-outlet run down to one client's coverage before it reaches a Google Sheets or Slack step. In Make, the Apify module supports run-and-wait, so a scheduled timeWindow: "1h" pull can feed an Airtable base or a digest email directly, using guid as the deduplication key so a repeated hourly run never inserts the same article twice. Both platforms handle scheduling, which is how you turn a single query into a rolling coverage archive without writing any code.

Collecting publicly published news metadata — headlines, publisher names, publish times and links — from a public RSS feed is broadly treated as permissible where no authentication is bypassed, and this Actor reads only anonymous public feeds with no account, cookie or session.

The primary regime here is contractual and copyright law, not personal-data law. This output is published editorial material about organisations and events: title, publisherName, publisherDomain, publishedAt and a link. There are no profiles, no user ids, no contact details and no author byline fieldpublisherName is an outlet such as Reuters, never an individual. GDPR and equivalent personal-data regimes therefore do not attach to this output the way they would to a profile scraper. The one nuance worth naming is that title is free text and a headline routinely contains a person's name, which makes that value incidental personal data even though the record is not a profile.

Two factual points on the copyright side. A headline and a snippet are fragments of a copyrighted work, and several jurisdictions grant press publishers specific neighbouring rights over exactly that kind of fragment, so the terms of Google News and of each publisher govern reuse. And republishing full article text is a legally distinct question from collecting links and metadata — one this Actor does not put you in, since it never fetches the publisher's page and returns no article body.

Consult legal counsel if your use case involves republishing headlines or snippets to the public, or building a competing news aggregation product from the collected dataset. This is factual framing, not legal advice.

❓ Frequently asked questions

What Google News fields does Google News Scraper By Publisher & Site Filter return?

The five most used are title, publisherDomain, publishedAt, matchedSite and link. Every row carries 28 keys in total, covering the article, the publisher, several views of its publish time, and the full provenance of the request that produced it. See the data fields table above for all of them.

Does it require a Google account, login or API key?

No. No Google account, no login, no cookie, no OAuth token and no API key of any kind — and there is no Google News API key to obtain, because Google publishes no public News API for third parties. The Actor reads the anonymous public RSS feeds. The only credential involved is your Apify token, and by default it does not even use a proxy.

Does it return the real publisher article URL, or the Google redirect?

The Google redirect. link and rssLink are both news.google.com/rss/articles/... URLs and this Actor does not decode them into the publisher's own article URL — there is no toggle for it. publisherHomeUrl and sourceUrl give you the outlet's homepage, and publisherDomain gives you the domain, but not the article path. If a fetchable article URL is a hard requirement for your pipeline, this is the wrong Actor, and the comparison question below names two listings that document resolving them.

Does it return the full article text?

No — you get a snippet. snippet is the RSS description with HTML stripped and the result truncated to 200 characters plus an ellipsis, and because the search feed's description is usually an anchor tag wrapping the headline and the outlet name, it often reads as little more than the headline again. The Actor never requests the publisher's page, so there is no body text, no standfirst and no word-count or reading-time field anywhere in the output.

How many articles can I get in one run?

One Google News request is capped at roughly 100 items and the surface has no pagination — independent queries measured 97 to 107 items on 2026-07-23, and num, start, count and scoring are all ignored. That ceiling is Google's, not the Actor's. To go past it, set maxItems above 100 and turn on deepCoverage, which re-runs the query across time shards and merges by guid: measured on 2026-07-23 and recorded in the Actor's input schema, 296 unique articles against 106 from a single request, and 577 against 100 for a 30-day range split into 6 shards. At or below 100, Deep Coverage is skipped as unnecessary.

What happens if my query or publisher filter returns zero articles?

You get a clean, empty run — no rows, no charges, and a log line saying which stage emptied it. There are three distinct cases and the log distinguishes them. If Google returned nothing at all, you get The feed returned no articles for this configuration. If every request was blocked or answered with something that was not an RSS document, you get Every feed request was blocked or returned an invalid document. And if articles came back but your own gates removed all of them, you get Every article was filtered out by the publisher or date filters. preceded by the exact counts kept and dropped by each gate. The most common cause of the third case is a publisherSites entry that never carries the story — set strictSiteFilter to false to see what the site: operator alone returned, then compare the publisherDomain values. Because no diagnostic rows are ever written, an empty dataset is itself the signal: check the log, not the dataset, for the reason.

Can I search several publishers, or several queries, at once?

Several publishers, yes — publisherSites and excludeSites are both arrays, and multiple entries become one (site:a OR site:b OR site:c) clause in a single request rather than one request per outlet. Several queries, no: query is a single string, so one run covers one keyword. Cover more by scheduling one run per query, or by calling the Actor once per query over the Apify API. Note that a broad publisher list plus a narrow keyword competes for the same ~100-item budget, so for many outlets at once, deepCoverage is what keeps each of them represented.

Does it work with Claude, ChatGPT and other AI agent tools, and is the output LLM-ready?

Yes to both. It is callable as a standard HTTP endpoint through the Apify API, so LangChain, CrewAI, n8n or a hand-written tool definition can invoke it and receive typed, normalized JSON with consistent field names across runs — no HTML parsing, no selectors, no cleanup pass. Pass a row straight into a context window, index it into a vector store, or hand it to an agent tool. One thing to tell the agent: link is a Google redirect, so an agent instructed to open and read each article will not be able to follow it through to the publisher's page.

How does it compare to other Google News scrapers?

Checked on the Apify Store on 25 July 2026. renzomacar/google-news-scraper documents decoding the Google redirect into the real publisher URL, returning url, urlResolved and googleNewsUrl, four modes (search, top stories, topic, location), and states up to 100 articles per run via maxItems. lhotanova/google-news-scraper documents advanced query operators including site:, intitle:, - and quoted phrases typed by hand into the query string, a fetchArticleDetails toggle that decodes article links and adds images, dateFrom/dateTo plus an openEndedDateRange field taking 1h/7d/1y shortcuts, hashed topic ids and topic sections, and day-by-day fetching when maxItems exceeds 100. easyapi/google-news-scraper documents maxItems in a 100–5000 range, the inputs query, gl, hl, lr, cr, nfpr and filter, and an output of position, title, link, domain, source, date, date_utc, snippet and a base64 data-URL thumbnail.

Observable differences in this Actor: publisher scoping is a first-class array input rather than operators you type into the query yourself, and it is enforced twice — as site: operators and again as a post-fetch re-check against the feed's own <source url> element, which is what produces the publisherDomain and matchedSite fields; the date window is likewise re-checked after the fetch, on the stated basis that after:/before: leaked 2 of 100 rows in a measurement on 2026-07-23; and lr, cr, nfpr and filter are documented as ignored by this surface rather than presented as working controls. The trade-off runs the other way on links: redirect resolution is documented on the renzomacar and lhotanova listings and is not offered here, and per-article images are documented on the lhotanova and easyapi listings and are not emitted here. These are field-list and input-flexibility differences you can verify on the listings yourself — not performance claims.

What happens when Google changes its feed or anti-bot system?

The scraper is maintained, and your field names and types stay put regardless. The exposure here is lower than for an HTML scraper, since RSS is a structured format rather than a rendered page, and the parser reads named elements rather than positional selectors — a missing element degrades to a null field rather than corrupting a good one. The soft-block guard is part of the same design: a response counts as blocked only when it does not parse as an RSS document at all, so a consent wall dressed as a 200 is caught and retried on a higher proxy tier rather than parsed into hollow rows.

Can I use it without managing proxies or browser infrastructure?

Yes, and that is the default. Google News RSS answers this Actor on a direct connection, so proxyConfiguration prefills to no proxy and most runs never need one. If a request is genuinely blocked, escalation is automatic — direct, then an Apify datacenter proxy, then Apify residential, up to three attempts per feed URL — and you never create a proxy account or rotate an IP yourself. There is no browser to run either: this is plain HTTP against an RSS endpoint, with no rendering and no captcha solving anywhere in it.

Which fields work best for AI training data and RAG indexing?

For RAG indexing: title is the high-information text field and snippet adds a little more, and they chunk best paired with publisherName and publishedAt so a retrieved chunk carries its own source and date instead of floating free. Include appliedQuery if you want each chunk to remember what was asked to find it. For training or modelling: publisherDomain, publishedAt, ageHours, feedMode and matchedSite are the structurally consistent fields across every record, and guid is the natural primary key for deduplicating across runs. Avoid training on date — it is relative prose computed at run time and means something different every time it is read. All values return as typed primitives — strings, numbers or null — so no normalization pass is needed before indexing.

Scraper NameWhat it extracts
Google Search Autocomplete Scraper with YouTube SuggestionsGoogle and YouTube autocomplete suggestion trees for a seed keyword
Google Maps Scraper with Reviews Sentiment AnalysisBusiness listings with reviews and per-review sentiment
Reddit Posts Scraper by Keyword & Score FilterReddit posts matching a keyword, filtered by score
X Twitter Posts SearchSearch results on X for a query — the reaction to a headline
Twitter Trends ScraperTwitter/X trending topics by country with hourly snapshots
Quora Search ScraperQuora questions and answers for a search term

💬 Your feedback

Found a bug, or need a feed mode, locale or filter that is not covered? Open an issue on the Actor's Issues tab. Reports that include the exact input JSON and the appliedQuery and loadedUrl values from a row that looked wrong are the fastest to reproduce, because those two fields reconstruct the exact request that was sent to Google.