Published
Google News API in Python: Search and Monitor Google News Results
Google does not offer an official Google News API. If you want Google News results in Python, for media monitoring, brand alerts, research, or a trading signal, you need an API that runs the search and returns the results as JSON. This guide uses PrismCrawl's Google News API to search Google News, page through results, and monitor keywords for new articles. It needs only Python 3 and the requests package.
Is there an official Google News API?
No. Google has no public API for searching Google News. You have two options:
- Google News RSS feeds. Free, but they return a limited set of fields and give you less control over pagination and targeting, and they are not a supported API.
- A Google News results API. A service such as PrismCrawl runs the search for a query, country, and language, and returns each article's title, URL, source, and age as JSON. You pay per request.
Set up
Create a PrismCrawl account to get an API key and 100 free credits, then store the key in an environment variable:
pip install requests
export PRISMCRAWL_API_KEY="replace-with-your-key"
Each successful Google News request uses one credit, and failed requests are free.
Search Google News
The Google News endpoint takes a query, a two-letter country, a language, and an optional page:
import os
import requests
API_URL = "https://api.prismcrawl.com/v1/google/news"
def search_news(query: str, **parameters) -> dict:
response = requests.post(
API_URL,
headers={
"x-api-key": os.environ["PRISMCRAWL_API_KEY"],
"content-type": "application/json",
},
json={"query": query, **parameters},
timeout=30,
)
response.raise_for_status()
payload = response.json()
if not payload.get("success"):
raise RuntimeError(payload.get("error", "Google News request failed"))
return payload["data"]["content"]
news = search_news("nvidia earnings", country="us", language="en")
for article in news["results"]:
print(f'{article["rank"]:>2} {article["source_name"]}: {article["title"]}')
print(f' {article["snippet"]} {article["url"]}')
Each result includes:
| Field | Example |
|---|---|
rank | 1 |
title | Nvidia Stock Slips. How Broadcom and Microsoft Are Shaking the Chip Sector. |
url | The article URL |
source_name | Barron's |
domain | barrons.com |
snippet | 3 hours ago |
Google shows article age as relative text, such as "3 hours ago". Store the time you collected each result alongside it, so you can work out an approximate publication time later.
Page through results
The response includes has_next_page. Request the next page until it is false or you have enough articles:
def search_all_news(query: str, max_pages: int = 3, **parameters) -> list[dict]:
articles = []
for page in range(1, max_pages + 1):
news = search_news(query, page=page, **parameters)
articles.extend(news["results"])
if not news.get("has_next_page"):
break
return articles
articles = search_all_news("electric vehicle tariffs", country="us", language="en")
print(len(articles), "articles")
Each page is a separate request and uses one credit.
Monitor keywords for new articles
To get alerts, run the search on a schedule and keep only URLs you have not seen. This version stores seen URLs in SQLite, so it works across restarts:
import sqlite3
from datetime import datetime, timezone
KEYWORDS = ["your brand", "your competitor", "your industry news"]
db = sqlite3.connect("news.db")
db.execute(
"""CREATE TABLE IF NOT EXISTS articles (
url TEXT PRIMARY KEY,
keyword TEXT,
title TEXT,
source TEXT,
age_text TEXT,
collected_at TEXT
)"""
)
def check_keywords() -> list[dict]:
new_articles = []
collected_at = datetime.now(timezone.utc).isoformat()
for keyword in KEYWORDS:
news = search_news(keyword, country="us", language="en")
for article in news["results"]:
inserted = db.execute(
"INSERT OR IGNORE INTO articles VALUES (?, ?, ?, ?, ?, ?)",
(
article["url"],
keyword,
article["title"],
article.get("source_name"),
article.get("snippet"),
collected_at,
),
).rowcount
if inserted:
new_articles.append({"keyword": keyword, **article})
db.commit()
return new_articles
for article in check_keywords():
print(f'[{article["keyword"]}] {article["title"]} {article["url"]}')
Run check_keywords() from cron, a scheduled cloud function, or a loop with a sleep, and send the new articles to Slack, email, or your own pipeline. The first run stores everything currently in the results; later runs return only new articles.
What it costs
One results page is one request. A few common monitoring setups:
| Setup | Requests per month | Cost with PrismCrawl |
|---|---|---|
| 10 keywords, every hour | 7,200 | $5 package (16,667 credits) |
| 50 keywords, every hour | 36,000 | $10 package (37,038 credits) |
| 200 keywords, every 15 minutes | 576,000 | $200 package (1,052,632 credits) |
Credits are one-time purchases valid for 90 days, with no subscription. See pricing for every package.
Other news sources
The same API key works for Bing News, DuckDuckGo News, and Baidu News, which cover different publishers and markets. Running the same keyword through two engines catches articles that one of them misses.
For complete projects built on live news, see building a Polymarket bot with live news, a Kalshi bot in Python, and the news trading bot for stocks and crypto. To get Google web results in Python, see the Google Search API Python guide.
Frequently asked questions
Is there an official Google News API?
No. Google does not offer a public API for searching Google News. To get Google News results in code, use a third-party API that returns the results page as JSON, or parse Google News RSS feeds, which have fewer fields and controls.
How do I get a Google News API key?
Because Google has no Google News API, there is no Google key to request. With PrismCrawl, create an account to get an API key and 100 free credits, then send it in the x-api-key header. Each successful Google News request uses one credit.
How much does it cost to monitor Google News?
Each page of Google News results is one request. Checking 50 keywords every hour is 36,000 requests a month, which costs about $10 with PrismCrawl at $0.27 per 1,000.