# Mostaql Projects Monitor (`abdulwhab95/mostaql-projects-monitor`) Actor

New freelance projects from mostaql.com, the largest Arabic freelance marketplace: title, category, skills, budget, bids, date and description. Filter by category, skill or keyword; schedule with onlyNew. No client personal data.

- **URL**: https://apify.com/abdulwhab95/mostaql-projects-monitor.md
- **Developed by:** [ABDULWAHAB NASER RASHED ALQARAWI](https://apify.com/abdulwhab95) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 5 total users, 2 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 projects

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

## Mostaql Projects Monitor

New freelance projects from **mostaql.com** — the largest Arabic freelance
marketplace — as clean rows: title, category, skills, budget, bids, publish time
and the full description.

Filter by category, skill or keyword, schedule it with **Only new**, and pay only
for projects you have not seen. No API key, no login, no browser, no proxy.

***

### What you get

One row per project, **13 fields, every one always present** — missing values
come back as `null`, never dropped.

| Field | Example |
|---|---|
| `title` | مسوّق إلكتروني محترف لمتجر منتجات رقمية |
| `category` | تسويق إلكتروني ومبيعات |
| `skills` | التسويق الإلكتروني, إنشاء حملة إعلانية, التسويق على تيك توك |
| `budgetMin` / `budgetMax` / `currency` | `50.0` / `100.0` / `USD` |
| `bidsCount` | `7` |
| `publishedAt` | `2026-09-15T00:26:33Z` (UTC) |
| `description` | full text, line breaks kept, markup removed |
| `url` | `https://mostaql.com/project/1260127` |

Plus `projectId`, `scrapedAt`, and `changeType` (`NEW` with **Only new**, else `null`).

**Times are real UTC.** The listing shows local-looking timestamps; the site's
own RSS feed gives the same project with `+0000`, so they are returned as ISO
8601 UTC.

***

### No personal data

This Actor **does not collect the client's name, username, avatar, profile
link or any contact information**, and nothing about the freelancers who bid.
Those elements sit on the same pages; they are never read. Each field is taken
from an element that holds only project data, and the tests check that a
client name, profile link, avatar and bidder name planted in a page never reach
a row.

***

### Filters

- **Categories** — programming, AI, design, marketing, writing & translation,
  business, engineering, support, training.
- **Skills** — a skill slug (`web-security`) or a link such as
  `https://mostaql.com/projects/skill/web-security`.
- **Keywords** — matched against title, description, skills and category.
  Case, Arabic diacritics and alef forms are ignored, so `مسوق` finds `مسوّق`
  and `الكتروني` finds `إلكتروني`. A project matches if it contains any keyword.
- **Minimum budget** (`minBudget`, USD) — a project matches when the top of its
  budget range (`budgetMax`) is at least this, so `$100–$250` matches `250`.
  A project with no stated budget never matches a minimum.
- **Published since** (`publishedSince`) — `2026-09-01` (00:00 UTC) or a
  date-time with a zone, such as `2026-09-01T08:00:00Z` or
  `2026-09-01T11:00:00+03:00`. It is compared with `publishedAt`, which is UTC.
  A malformed value stops the run before any request; a project with no
  publish time never matches.

All filters are checked on the project page before a row is delivered, so a
project that does not match is never charged. With `onlyNew`, the minimum
budget and the since-date become part of the remembered state's key only when
set: an existing monitor that does not use them keeps its memory.

With both skills and categories, the skill listings are read and each project's
own category is checked.

***

### Only new projects

Turn on `onlyNew` and schedule the Actor (every hour, say). Each run delivers
only projects that no earlier run delivered, marked `changeType: NEW`. Known
projects are recognised from the listing alone, so their pages are not read
again.

Measured 15 Sep 2026, on all categories with `maxPages: 2`:

| Run | Requests | Time | Projects delivered |
|---|---|---|---|
| First | 53 | 59.9 s | 50 (all `NEW`) |
| Second, one minute later | 3 | 2.4 s | 0 |

How it remembers:

- Project ids are kept in a named key-value store in your account
  (`stateStoreName`, default `mostaql-projects-state`), under a key built from
  your filters. Two monitors with different filters never hide each other's
  projects.
- A project that was read but did not match your keywords is remembered too, so
  it is not read again on every run.
- A project that was **not** delivered — its page failed, or the run stopped at
  your spending limit — is not remembered and is tried again next run.
- If a run stops at `maxProjects`, projects further down the listing are still
  unseen and are delivered by the next run. They are older, not new; set
  `maxProjects` to at least `maxPages × 25` if you want each run to cover its
  whole window.

***

### Speed and politeness

One request at a time, **at least one second apart**. A run reads one listing
page per 25 projects plus one page per project it has not seen.

Measured 15 Sep 2026: **50 projects in 59.9 seconds** (53 requests).

- `robots.txt` is read at the start of every run and obeyed for every URL.
  On 15 Sep 2026 it disallowed only `/search` and `/ajax/`; the Actor never
  requests either, even through a redirect.
- Every request, redirects included, must stay on `https://mostaql.com`.
- `maxPages` (default 5, at most 40) bounds every run.
- If the site answers "too many requests", the Actor waits (up to 30 s) and
  tries once more. If it refuses again, answers 403, or shows a challenge page,
  the run **stops** and says so. There is no attempt to get around a block.

***

### Honest notes

**Bids count comes from the listing.** The project page lists the bids but not
their number; the listing states it (`7 عروض`, `عرض واحد`, `أضف أول عرض` = 0).

**Budgets are in US dollars.** Every budget seen on 15 Sep 2026 was written in
`$`. `currency` is `null` if a budget ever appears without a currency sign.

**A project page that cannot be read is skipped**, counted under `unreadable`
in the run report, and — with `onlyNew` — tried again next run.

**Every run publishes a report** to the key-value store under `RUN_REPORT`:
requests, listing pages read, projects read, already seen, filtered out,
unreadable, and whether the run stopped at a block, the spending limit or
`maxProjects`.

***

### Questions, or a project that looks wrong?

Open an issue with the project link.

# Actor input Schema

## `categories` (type: `array`):

Only projects in these categories. Leave empty for all categories.

## `skills` (type: `array`):

Only projects tagged with one of these skills. One per line: a skill slug (web-security) or a mostaql.com/projects/skill/... link. Leave empty for all skills.

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

Only projects whose title, description, skills or category contain at least one of these words (Arabic or English; case, diacritics and alef forms are ignored). Leave empty for no keyword filter.

## `minBudget` (type: `number`):

Optional. Only projects whose budget range reaches this amount (the top of the range, budgetMax, is at least this). A project with no stated budget never matches. Empty or 0: no minimum.

## `publishedSince` (type: `string`):

Optional. Only projects published at or after this moment. An ISO date (2026-09-01, meaning 00:00 UTC) or a date-time with a zone (2026-09-01T08:00:00Z, 2026-09-01T11:00:00+03:00). Anything else stops the run before any request. A project with no publish time never matches.

## `maxProjects` (type: `integer`):

Stop after delivering this many projects.

## `maxPages` (type: `integer`):

Listing pages read per category or skill (25 projects per page, newest first). Keeps each run short and polite.

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

Deliver only projects not delivered (or already checked against your filters) by an earlier run. Rows carry changeType NEW. The first run delivers everything it reads.

## `stateStoreName` (type: `string`):

Named key-value store that remembers project ids for 'Only new'. Use a different name to keep separate monitors apart.

## Actor input object example

```json
{
  "categories": [],
  "skills": [],
  "keywords": [
    "ووردبريس",
    "python"
  ],
  "publishedSince": "",
  "maxProjects": 50,
  "maxPages": 5,
  "onlyNew": false,
  "stateStoreName": "mostaql-projects-state"
}
```

# Actor output Schema

## `results` (type: `string`):

No description

## `runReport` (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 = {
    "keywords": [
        "ووردبريس",
        "python"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("abdulwhab95/mostaql-projects-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": [
        "ووردبريس",
        "python",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("abdulwhab95/mostaql-projects-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": [
    "ووردبريس",
    "python"
  ]
}' |
apify call abdulwhab95/mostaql-projects-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,abdulwhab95/mostaql-projects-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/G9zRwrDG1UBjMqfrI/builds/brnRSInp3gI58RIde/openapi.json
