# Gulf Business News Monitor (Arabic & English) (`pharaoh_data/gulf-business-news-monitor`) Actor

Track Saudi, UAE, and GCC business news from publisher RSS feeds in Arabic and English. Get only new stories matching your companies and keywords, with duplicate coverage merged across outlets.

- **URL**: https://apify.com/pharaoh_data/gulf-business-news-monitor.md
- **Developed by:** [Pharaoh Data](https://apify.com/pharaoh_data) (community)
- **Categories:** News, AI, Marketing
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 news stories

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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

## What's an Apify Actor?

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

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

## How to integrate an Actor?

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

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

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

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

# README

## Gulf Business News Monitor (Arabic & English)

### Get only the new Gulf business stories that mention your companies and topics

Track Saudi, UAE, and wider GCC business news from publisher RSS feeds in **Arabic and English**. Add the company names, topics, and sectors you care about. Each run returns only the **new** headlines that match, with links to the original articles, the publisher's own summary, GCC country tags, and the same story merged when several outlets publish it.

**Built for:** communications and PR teams, investor relations, market and competitive intelligence analysts, and sales teams following accounts in Saudi Arabia, the UAE, and the GCC. It also fits AI agents that need a clean, deduplicated Gulf news feed.

### What you get

- **A verified Gulf publisher catalog** of 13 feeds that were live and allowed by robots.txt when checked on 2026-10-17: Saudi Gazette, Gulf News, Khaleej Times, The National (all and business), Asharq Al-Awsat (English and الشرق الأوسط), سكاي نيوز عربية, BBC عربي, Wamda, News of Bahrain, Oman Observer, and Fast Company Middle East.
- **Your own feeds too:** company newsrooms, regulators, and trade publications that publish RSS or Atom.
- **Arabic-aware keyword matching:** diacritics and spelling variants (أ/إ/ا, ى/ي, ة/ه) are ignored, and attached prefixes are handled, so `أرامكو` matches `وأرامكو` and `لأرامكو`, and `اقتصاد` matches `للاقتصاد`. English matches whole words (`AI` does not match "said"); add `*` for prefixes (`IPO*` matches "IPOs").
- **New stories only:** the monitor remembers what it returned, so scheduled runs deliver each story once.
- **Merged coverage:** the same story from several publishers (same URL or same headline) becomes one record with `alsoPublishedBy`.
- **GCC tagging and filters:** stories are tagged with the GCC countries they mention (English and Arabic place names), and can be filtered by country, language, and age.
- **Run summary:** per-feed status, keyword counts, and country counts in `RUN_SUMMARY`.

### Quick start

1. Keep the default publishers or pick your own under **Publisher feeds**. Add extra RSS/Atom URLs under **Additional feeds**.
2. Add **Keywords and company names** in either language, for example `Aramco`, `أرامكو`, `PIF`, `صندوق الاستثمارات العامة`, `fintech`, `IPO*`.
3. Optionally set **Countries** (for example Saudi Arabia) and **Exclude keywords** (for example `football`, `كرة القدم`).
4. Run it, then save it as a task with a schedule (for example every 2 hours) and connect a webhook or integration for alerts.

#### Example input

```json
{
    "presets": ["saudi-gazette", "gulf-news", "the-national-business", "asharq-al-awsat-ar", "sky-news-arabia"],
    "feedUrls": [],
    "keywords": ["Aramco", "أرامكو", "PIF", "صندوق الاستثمارات العامة", "fintech", "IPO*"],
    "excludeKeywords": ["football", "كرة القدم"],
    "countries": ["SA", "AE"],
    "languages": [],
    "maxAgeHours": 48,
    "onlyNew": true,
    "monitorId": "saudi-ipo-watch",
    "maxItems": 300
}
```

#### Input reference

| Field             | Default      | What it does                                                                                                      |
| ----------------- | ------------ | ----------------------------------------------------------------------------------------------------------------- |
| `presets`         | 7 Gulf feeds | Catalog feeds to read.                                                                                            |
| `feedUrls`        | `[]`         | Extra public RSS/Atom feed URLs. Up to 50 feeds per run in total.                                                 |
| `keywords`        | `[]`         | Keep stories whose headline or summary contains any term (whole words; `*` suffix for prefixes). Empty keeps all. |
| `excludeKeywords` | `[]`         | Drop stories containing any of these.                                                                             |
| `countries`       | `[]`         | Keep stories that mention a selected GCC country or come from a publisher based there.                            |
| `languages`       | `[]`         | `en`, `ar`, or both (detected from the headline).                                                                 |
| `maxAgeHours`     | `48`         | Ignore stories older than this; `0` disables. Undated stories are kept.                                           |
| `onlyNew`         | `false`      | Return only stories this monitor has not returned before. Turn on for scheduled alerts.                           |
| `monitorId`       | auto         | Name of the history. When empty it is derived from feeds and filters, so changing them starts a fresh history.    |
| `maxItems`        | `300`        | Maximum stories saved per run, newest first. Each saved story is one billable result.                             |
| `maxItemsPerFeed` | `100`        | Items read from each feed before filtering.                                                                       |
| `includeSummary`  | `true`       | Include the publisher's feed summary (up to 500 characters).                                                      |

### Output

```json
{
    "itemId": "5cee5a23218901eff2cd1db05e285407",
    "title": "لماذا لا تنعكس التصنيفات الإيجابية للاقتصاد المصري على وضع الجنيه؟",
    "url": "https://aawsat.com/node/5330599",
    "publisher": "الشرق الأوسط",
    "feedId": "asharq-al-awsat-ar",
    "feedUrl": "https://aawsat.com/feed",
    "sourceCountry": "",
    "language": "ar",
    "publishedAt": "2026-10-17T16:06:56.000Z",
    "summary": "…the publisher's own feed summary, up to 500 characters…",
    "categories": ["شمال افريقيا"],
    "imageUrl": "https://static.example-cdn.com/image.webp",
    "countries": [],
    "matchedKeywords": ["اقتصاد"],
    "alsoPublishedBy": [],
    "isNew": true,
    "firstSeenAt": "2026-10-17T16:39:10.067Z",
    "scrapedAt": "2026-10-17T16:39:10.067Z"
}
```

`RUN_SUMMARY` (default key-value store) lists each feed's status (`ok`, `failed`, or `blocked-by-robots`) with its error, items read, matching and stored counts, plus totals, keyword counts, and country counts.

### Use it from code, n8n, Make, or an AI agent

```bash
curl -X POST "https://api.apify.com/v2/acts/pharaoh_data~gulf-business-news-monitor/run-sync-get-dataset-items?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["Aramco","أرامكو"],"countries":["SA"],"monitorId":"aramco-alerts"}'
```

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('pharaoh_data/gulf-business-news-monitor').call({
    keywords: ['PIF', 'صندوق الاستثمارات العامة'],
    monitorId: 'pif-watch',
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
```

- **Alerts:** schedule a task and add a webhook on "Run succeeded" that posts new stories to Slack, Teams, or email (n8n, Make, and Zapier all have Apify integrations).
- **AI agents (MCP):** connect `https://mcp.apify.com/?actors=pharaoh_data/gulf-business-news-monitor` so an agent can fetch fresh Gulf headlines as a tool.

### Responsible use and limits

- The Actor reads **RSS and Atom feeds only**. It returns headlines, links, the publisher's own feed summary, categories, and image links. It never downloads article pages or full article text, and it does not collect author bylines.
- robots.txt is **always** checked for every feed and redirect; disallowed feeds are reported as `blocked-by-robots`. Redirects are followed only within the same site, at most three times. Each host is contacted at most once per second, or slower if robots.txt sets a crawl delay. There are no proxies, logins, or challenge-solving.
- Feeds behind bot protection are left out of the catalog because they refuse automated clients. These include Arab News, Zawya, Al Arabiya, Arabian Business, and Gulf Business. No catalog feed currently covers Qatar or Kuwait; add publisher feeds you are permitted to use with `feedUrls`.
- Publishers own their content. Feeds are generally offered for reading and linking. Before republishing headlines or summaries, using them commercially beyond internal monitoring, or using them for AI training, check each publisher's terms and get a license where needed.
- Matching is lexical, not semantic, and Arabic prefix handling can occasionally over-match short words. Use specific terms and `excludeKeywords`.
- History is kept for 30 days in your account's named key-value store `gulf-news-monitor-state`, under `monitor-<monitorId>`.

### Pricing

Pay per event: you pay per **saved story** (one dataset record), plus Apify's small Actor start event. "Only new stories" keeps scheduled runs cheap because already-delivered stories are not saved or charged. See the **Pricing** tab for current amounts. A typical run reads 13 feeds in about 20 seconds with 256 MB of memory.

### FAQ

**Why did a feed fail?**
Publishers change feed URLs or add bot protection. `RUN_SUMMARY` shows the error for each feed, and the other feeds still run.

**Can I monitor a regulator or a company newsroom?**
Yes, if it publishes RSS or Atom and its robots.txt allows it. Add the URL under `feedUrls`.

**Does it translate or summarize?**
No. It returns the publisher's own headline and summary in the original language.

# Actor input Schema

## `presets` (type: `array`):

Verified public RSS feeds from Gulf and regional publishers. The list is checked for availability and robots.txt permission; feeds can change, and failures are reported per feed in RUN_SUMMARY.

## `feedUrls` (type: `array`):

Any other public RSS or Atom feed URLs, such as a company newsroom, a regulator, or a trade publication. Only add feeds you are permitted to use. robots.txt is always respected.

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

Keep stories whose headline or summary contains any of these, as whole words. Arabic and English are supported; Arabic matching ignores diacritics, spelling variants, and attached prefixes such as و، ب، ال. End a term with \* for a prefix match (bank\* matches banking). Leave empty to keep every story.

## `excludeKeywords` (type: `array`):

Drop stories that contain any of these terms, for example football or كرة القدم.

## `countries` (type: `array`):

Keep stories that mention one of these countries (English or Arabic place names), or that come from a publisher based there. Leave empty for no country filter.

## `languages` (type: `array`):

Keep stories in these languages, detected from the headline. Leave empty for both.

## `maxAgeHours` (type: `integer`):

Ignore stories published longer ago than this. 0 keeps every story in the feed. Stories without a date are kept.

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

Return only stories this monitor has not returned in an earlier run, for scheduled alerts. When off, every matching story is returned each run, with isNew showing which are new.

## `monitorId` (type: `string`):

Optional name for this monitor's history, such as "aramco-watch". When empty, an ID is derived from the feeds and filters. History is kept for 30 days in your account's named key-value store gulf-news-monitor-state.

## `maxItems` (type: `integer`):

Upper limit on saved stories, newest first. Each saved story is one billable result.

## `maxItemsPerFeed` (type: `integer`):

Items read from each feed before filtering.

## `includeSummary` (type: `boolean`):

Include the summary the publisher puts in its feed (up to 500 characters). Full article text is never collected.

## Actor input object example

```json
{
  "presets": [
    "saudi-gazette",
    "gulf-news",
    "khaleej-times",
    "the-national-business",
    "asharq-al-awsat-ar",
    "sky-news-arabia"
  ],
  "feedUrls": [],
  "keywords": [
    "Aramco",
    "أرامكو",
    "PIF",
    "IPO",
    "Saudi",
    "السعودية",
    "UAE",
    "الإمارات"
  ],
  "excludeKeywords": [],
  "countries": [],
  "languages": [],
  "maxAgeHours": 48,
  "onlyNew": false,
  "monitorId": "",
  "maxItems": 300,
  "maxItemsPerFeed": 100,
  "includeSummary": true
}
```

# Actor output Schema

## `stories` (type: `string`):

Dataset of matching stories, newest first.

## `runSummary` (type: `string`):

Per-feed status, keyword and country counts, and totals.

# 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": [
        "Aramco",
        "أرامكو",
        "PIF",
        "IPO",
        "Saudi",
        "السعودية",
        "UAE",
        "الإمارات"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("pharaoh_data/gulf-business-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": [
        "Aramco",
        "أرامكو",
        "PIF",
        "IPO",
        "Saudi",
        "السعودية",
        "UAE",
        "الإمارات",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("pharaoh_data/gulf-business-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": [
    "Aramco",
    "أرامكو",
    "PIF",
    "IPO",
    "Saudi",
    "السعودية",
    "UAE",
    "الإمارات"
  ]
}' |
apify call pharaoh_data/gulf-business-news-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,pharaoh_data/gulf-business-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/VbQgfCeAc9VRfPfTC/builds/vx2Pn5439edKmzbqF/openapi.json
