# Bing News Monitor — Articles by Keyword, New Since Last Run (`northbell/bing-news-monitor`) Actor

News monitor for any keyword from Bing News: title, publisher, publish time, snippet, image and the publisher link, newest first, in 43 country editions. Run it on a schedule and every article is marked new or already seen since the last run, with the rank change. No login, no API key.

- **URL**: https://apify.com/northbell/bing-news-monitor.md
- **Developed by:** [Northbell](https://apify.com/northbell) (community)
- **Categories:** News, Marketing
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.80 / 1,000 articles

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

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

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Bing News Monitor — Articles by Keyword, New Since Last Run

Give it a list of keywords — a company, a product, a person, a topic — and get a clean news list back: **title, publisher, publish time, snippet, image and the publisher's own link** for each article, newest first, from the public Bing News search page in 43 country editions. A simple **news monitor, news scraper and news API** in one: **$1 per 1,000 articles**, no login, no API key.

Run it again — or put it on a schedule — and every article is also marked **new or already seen since the last run**, with the rank it had last time. Turn on *Only articles that are new* and you get just what appeared since your last run, and pay only for that.

### What you get

One row per article (`type: "article"`):

| Field | What it is |
|---|---|
| `keyword`, `market` | the search that found it, and the Bing News edition (for example `en-US`, `ja-JP`) |
| `title`, `titleTruncated` | the headline; `titleTruncated` is `true` when Bing itself cut it short ("…" or " ...") |
| `url`, `domain` | the publisher's page (Bing's tracking marks and `utm_` marks removed) and its domain |
| `publisher` | the outlet name as Bing shows it (" on MSN" / " via MSN" labels removed) |
| `publishedAt`, `publishedAtPrecision` | publish time, ISO 8601 UTC, and how exact it is: `minute`, `hour`, `day`, `week`, `month` or `year` (see Notes: Bing shows "5 hours ago", not a clock time). `null` when the label cannot be read |
| `publishedText` | the time label exactly as Bing writes it in that edition's language, for example `5 hours ago`, `Vor 15 Stunden`, `1 時間前` or an exact date such as `8/26/2026` |
| `description` | Bing's text excerpt of the article (about 200 characters), plain text, with email addresses and phone numbers removed; a wire-service byline ("By Jane Roe … (Reuters) -") is moved to `authors` |
| `authors` | the author names from a wire-service byline at the start of the excerpt (empty when there is none) |
| `imageUrl` | Bing's thumbnail of the article image, when the article has one |
| `rank` | position in this run's list, 1 = newest |
| `isNewSinceLastRun` | `true` if this keyword and market never returned this article before, `false` if it did, `null` on the first run |
| `firstSeenAt` | when this Actor first saw the article — compare with `publishedAt` to see how late Bing listed it |
| `previousRank`, `rankChange` | the rank in your previous run and how far the article moved (positive = moved up); `null` when it was not in the previous list |

One free **summary row per keyword** (`type: "summary"`): `articlesRead`, `articlesReturned`, `newSinceLastRun`, `firstRun`, `publishersTop` (the 10 publishers with the most articles, with counts), `newestPublishedAt`, `oldestPublishedAt`, `queryUsed`, `complete`, and `servedRegion`, `servedLanguage`, `marketHonored` (which edition Bing really served, and whether it is the one you asked for). Keywords that could not be read give a free `type: "error"` row with a `message`.

### Use it for

- **Brand, competitor and PR monitoring** — schedule it every few hours, send the new articles to Slack, Sheets or your CRM
- **Content and SEO research** — see who covers a topic, which publishers write about it most (`publishersTop`) and how fresh the coverage is
- **News data for dashboards, newsletters and AI agents** — a news API with stable fields in 43 languages and countries, no key to manage
- **Market and investor watchlists** — one keyword per company or ticker, `onlyNew` to get only what you have not seen

### Input

```json
{ "keywords": ["openai", "\"electric vehicles\"", "site:reuters.com tesla"], "market": "en-US", "freshness": "day", "maxArticlesPerKeyword": 50, "onlyNew": false }
```

- **keywords** — one search per line. Put a phrase in "double quotes" to match it exactly, or limit a search to one publisher with `site:reuters.com`.
- **market** — the Bing News edition: language and country of the results (`en-US`, `en-GB`, `de-DE`, `ja-JP`, `pt-BR` …).
- **freshness** — any time, past hour, past 24 hours (default), past week or past month. Results are always newest first. For every window longer than an hour the Actor also reads Bing's "past hour" list and adds it (see Notes), so the newest articles are not missing.
- **maxArticlesPerKeyword** — 1 to 200 (default 50). Bing lists about 190 articles per search at most.
- **onlyNew** — return only articles not seen before for that keyword and market.

What was seen is remembered per keyword and market in a named key-value store in your Apify account, so the second run of the same Actor already shows what is new. Schedule it (Apify → Schedules), for example every 6 hours with *Past 24 hours*.

### Pricing

**$1.00 per 1,000 articles**, plus $0.01 per run. Summary rows and error rows are free, and with *Only articles that are new* you pay only for the new ones. The $0.01 run-start fee is the one charge every run pays, even one that returns nothing.

### Notes

- Public data only: what anyone sees on the Bing News search page without signing in. Article text is not downloaded — you get the headline, Bing's excerpt and the link.
- **The time is computed, not copied.** The page shows how long ago an article came out ("16 minutes ago", "5 hours ago", "3 days ago"), and an exact date only for older ones. `publishedAt` is the moment of the read minus that age, so it is as exact as the unit shown: "5 hours ago" means between 5 and 6 hours, and `publishedAt` is the newest it can be. `publishedAtPrecision` tells you the unit (`minute` for seconds and minutes). For an exact date (`8/26/2026`) `publishedAt` is that day at 00:00 UTC and the precision is `day`. The label is read in 20 languages; if it cannot be understood, `publishedAt` is `null` and `publishedText` still has the label. The same article can show a `publishedAt` an hour apart in two runs, so identify articles by `url`.
- The first run for a keyword (and market) has nothing to compare with, so `isNewSinceLastRun`, `previousRank` and `rankChange` are `null` and *Only articles that are new* returns everything. Changing the market starts a new history. Changing *How recent* keeps what was already seen, but the first run after the change has no `previousRank` (two different lists are not compared).
- **The newest articles come from a second list.** Bing's "past 24 hours", "past week" and "any time" lists are a selection of about 100 articles that Bing picks by relevance and then sorts by time, and that selection leaves out most of the very newest articles. In my test of 12 keywords, 44 of the 51 articles in Bing's own "past hour" list were missing from its "past 24 hours" list. So for every window except "past hour" the Actor also reads the past-hour list (a few extra requests per keyword), merges it in, and sorts everything by time; if the past-hour list cannot be read you get the main list plus a free `error` row and `complete: false`. Bing still shows only part of a busy day: the list holds at most about 95 articles for 24 hours or 7 days, so run it every few hours with *Only articles that are new* instead of asking for a whole day at once.
- Bing's list shifts a little from one call to the next, so now and then an article that was published earlier shows up as new. `firstSeenAt` (the moment the keyword was read) against `publishedAt` tells you which case it is.
- Because the list is sorted by time, `rankChange` is mostly zero or negative (older articles slide down as newer ones arrive). It is most useful with *Any time*.
- Bing lists up to about 190 articles for a search with *Any time*, about 135 for the past 30 days and about 95 for the past 24 hours or 7 days (fewer when a keyword has little news). Asking for more than exists returns what exists; `articlesRead` in the summary row says how many that was.
- **A keyword that is an outlet's own name can return only that outlet.** For "Premier League" in `en-GB` and "Bundesliga" in `de-DE`, Bing returned only the official site's own articles (6 and 12 in a week). Add a second word ("Premier League Arsenal" returned a wide mix of publishers) to get the general coverage.
- `imageUrl` is empty for about a quarter to a third of the articles — the card has no picture (86 of 307 in my count). It is Bing's small thumbnail, not the original image.
- Bing cuts excerpts at about 200 characters, so most `description` values end in "...". Long headlines are cut in some editions: none of 187 English headlines in my test, but 29 of 40 in the Japanese edition; `titleTruncated` tells you when. Syndicated articles on MSN have `domain` `msn.com` and the original outlet in `publisher`.
- If more new articles appear between two runs than *Max articles per keyword*, the oldest of them are not read: run more often, shorten *How recent*, or raise the limit.
- Search words: quotes make an exact phrase and `site:reuters.com` restricts the publisher (both worked in my tests); `OR` between two terms returned articles for both sides; `-word` only reduces the matches (in my test, `tesla -musk` still returned 4 of 30 articles with "musk" in the headline or excerpt, down from 6). A keyword that Bing treats as a topic instead of a search — a category word such as "technology" or "sports", or a place name such as "Malaysia" in the `en-MY` edition — is read as an exact phrase automatically; `queryUsed` shows it.
- **The market is a setting, not a guarantee.** Apify runs in the US, and I could only test from a connection in Japan, where the setting won over my own location for all 43 editions: for `tesla` in the past week, `en-GB` shared 18 of 25 articles with `en-US`, `en-AU` 17, while `de-DE` and `ja-JP` shared none (13 of the 25 `de-DE` articles came from `.de` sites; the Japanese edition answered in Japanese). Small editions mix in articles from other languages once the local ones run out, and a general keyword such as "openai" sorted newest-first returns many English or Chinese articles in any edition — use a local keyword for local news. I could not test from Apify's own servers, so every keyword summary row reports `servedRegion`, `servedLanguage` and `marketHonored` (`false` when Bing served another edition than the one you chose, and the run log warns). `zh-CN` has no Bing News edition.

To see how search interest in a keyword moves over time next to the news, see [Google Trends Scraper](https://apify.com/northbell/google-trends-tracker).

### For AI agents

`{"keywords": ["openai"], "freshness": "day", "maxArticlesPerKeyword": 20}` returns up to 20 article rows plus one summary row. Rows have `type`: `article`, `summary` or `error`. To poll for news, call it on a schedule with `"onlyNew": true` and read only the `article` rows; `isNewSinceLastRun` is `true` for what has not been returned before. Identify an article by `url`, not by `publishedAt`, which is computed from an age such as "5 hours ago".

# Actor input Schema

## `keywords` (type: `array`):

One search per line: a company, product, person, topic or phrase. Put a phrase in "double quotes" to match it exactly, or limit a search to one publisher with site:reuters.com. OR between two terms works; -word only reduces the matches, it does not remove every article with that word. Each keyword is read and remembered separately.

## `market` (type: `string`):

Which Bing News edition to read. It sets the language and country of the results, so use ja-JP for Japanese news, de-DE for German news and so on. The keyword summary row shows which edition Bing actually served.

## `freshness` (type: `string`):

Only articles published within this window. Results are always newest first. Pick "Past 24 hours" and run it every few hours for a news monitor. For every window except "Past hour" the Actor also reads Bing's past-hour list, because Bing's longer lists leave out most of the newest articles.

## `maxArticlesPerKeyword` (type: `integer`):

How many of the newest articles to read for each keyword. Bing lists about 190 per search at most (fewer with a short time window), so asking for more returns what exists.

## `onlyNew` (type: `boolean`):

Return only articles this keyword has not shown before (you pay only for those). The first run has nothing to compare with, so it returns everything. The keyword summary row is always returned.

## Actor input object example

```json
{
  "keywords": [
    "openai"
  ],
  "market": "en-US",
  "freshness": "day",
  "maxArticlesPerKeyword": 50,
  "onlyNew": false
}
```

# Actor output Schema

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

News articles per keyword with publisher, publish time, snippet, image and the since-last-run marks.

## `summaries` (type: `string`):

Per keyword: articles read, how many are new since the last run, and the top publishers.

# 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 = {
    "keywords": [
        "openai"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("northbell/bing-news-monitor").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 = { "keywords": ["openai"] }

# Run the Actor and wait for it to finish
run = client.actor("northbell/bing-news-monitor").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 '{
  "keywords": [
    "openai"
  ]
}' |
apify call northbell/bing-news-monitor --silent --output-dataset

```

## MCP server setup

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

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/y8xAMvzkCZifFEI37/builds/ymtDuxiHhQdOcSdoH/openapi.json
