# MENA Classifieds Scraper — Hatla2ee & OpenSooq (`fourarms_4x4/mena-classifieds`) Actor

Scrape Hatla2ee and OpenSooq classified listings into a structured dataset: titles, prices with currency, city, post age and listing URLs. Covers Egyptian used cars and MENA classifieds ads across both marketplaces.

- **URL**: https://apify.com/fourarms\_4x4/mena-classifieds.md
- **Developed by:** [Ahmed Hazem](https://apify.com/fourarms_4x4) (community)
- **Categories:** E-commerce, Real estate, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## 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

## MENA Classifieds Scraper — Hatla2ee & OpenSooq

### What does MENA Classifieds Scraper do?

Scrapes classified listings from **[Hatla2ee](https://www.hatla2ee.com/)** (Egypt's largest car marketplace) and **[OpenSooq](https://www.opensooq.com/)** (the largest general classifieds network in MENA). It walks listing and pagination pages, follows each car detail page on Hatla2ee, and returns a structured Apify dataset — title, price, currency, city, post age, listing URL — exportable as JSON, CSV, Excel or XML, with API access, scheduling and monitoring on the Apify platform.

### Why use it?

- **Little competing coverage** for Egyptian and Levant classifieds on data platforms.
- Use cases: **lead generation** for dealers and brokers, **price monitoring**, **market research**, **Arabic-language AI training data**.
- Runs over plain HTTP (fast and cheap); no login or cookies needed for public listings.

### How to use

1. Add the Actor to your Apify account.
2. On the Input tab, keep or edit the **Start URLs** (prefilled with Hatla2ee cars + OpenSooq cars).
3. Set **Max items per source** and **Max pages (whole run)** to control run cost.
4. Click **Start**, then download the dataset from the Output tab (or pull it from the API).

### Input

| Field | Type | Default | Description |
|---|---|---|---|
| start\_urls | array | Hatla2ee `/ar/car` + OpenSooq `/en/cars` | Listing/category URLs on hatla2ee.com or opensooq.com. Both `{"url": …}` objects and plain URL strings work. |
| max\_items | integer | 50 | Upper limit on listings pushed **per source** (0 = unlimited). A run with both sources can return up to twice this. |
| max\_requests\_per\_crawl | integer | 20 | Hard cap on pages fetched by the **whole run** — listing, pagination and detail pages combined. This is the cost lever. |
| proxyConfiguration | object | Apify Proxy off | Optional. Supply Apify Proxy or your own proxy URLs if a source starts blocking runs. |

### Output

Example dataset item (OpenSooq):

```json
{
  "source": "opensooq",
  "sourceUrl": "https://eg.opensooq.com/en/cars",
  "listingUrl": "https://eg.opensooq.com/en/cars/287687414",
  "listingId": "287687414",
  "title": "كيا برايد 99 اوتوماتيك",
  "priceText": "190,000 EGP",
  "priceAmount": "190000",
  "priceCurrency": "EGP",
  "city": "Cairo",
  "postedAt": "1 hour ago"
}
```

Example dataset item (Hatla2ee — no city or postedAt on this source):

```json
{
  "source": "hatla2ee",
  "sourceUrl": "https://www.hatla2ee.com/ar/car/citroen/C5/7291889",
  "listingUrl": "https://www.hatla2ee.com/ar/car/citroen/C5/7291889",
  "listingId": "7291889",
  "title": "سيتروين C5 2020 للبيع مدينة نصر",
  "priceText": "1120000 EGP",
  "priceAmount": "1120000",
  "priceCurrency": "EGP",
  "city": null,
  "postedAt": null
}
```

You can download the dataset as JSON, CSV, Excel or XML.

### Data table

| Field | Type | Description |
|---|---|---|
| source | string | `hatla2ee` or `opensooq` |
| sourceUrl | string | page the item came from |
| listingUrl | string | canonical listing URL (both sources) |
| listingId | string | site-native listing id |
| title | string | listing title, Arabic or English, as published (site boilerplate trimmed) |
| priceText | string | price as displayed by the source — `190,000 EGP` (OpenSooq) or `1120000 EGP` (Hatla2ee) |
| priceAmount | string | price digits only, e.g. `1120000` (cast to int/float downstream) |
| priceCurrency | string | currency code, e.g. `EGP` |
| city | string | seller city (OpenSooq; `null` on Hatla2ee) |
| postedAt | string | relative post age as shown (OpenSooq), e.g. `2 hours ago` |

Keys are always present on every row, so CSV/Excel exports keep a stable column
set; fields a source does not expose come back `null` rather than being invented.

### Pricing / cost estimation

#### How much does it cost to scrape Hatla2ee and OpenSooq listings?

**Free to run at launch.** You pay only the Apify platform usage your run generates — there is no charge for the data itself. Pay-per-event pricing (a small fee per extracted listing) is planned once the Actor has a track record of runs and reviews.

Cost is bounded by `max_requests_per_crawl`: a 20-page run stays within the free Apify plan's monthly credits, so a full test costs nothing. Pages that fail permanently are counted against that budget as well, so a blocked or unreachable target cannot quietly burn credits. For reference, one Hatla2ee detail page yields 1 listing, and a listing page yielded 29 detail links in testing.

### Tips

- **Deeper coverage:** `max_requests_per_crawl` is shared by every page type, and detail pages are fetched first (1 page ≈ 1 listing), so raise it together with `max_items` to walk more listing pages. Hatla2ee pagination (`/ar/car/page/2`, …) and OpenSooq pagination (`?page=2`) are followed automatically.
- The actor obeys `robots.txt` on both sources (their wildcard rules allow the paths this Actor scrapes) and fetches at a browser-like rate (~120 pages/minute, concurrency 3) to stay polite.
- Blocked? Add `proxyConfiguration` — residential proxies may be needed if a source tightens anti-bot rules.
- Use Apify **schedules** for daily price-watch runs.

### FAQ & disclaimers

- **Personal data:** listing titles and bodies come from public pages; phone numbers, seller names and contact details are deliberately **not** extracted.
- Content is provided as-is, no warranty of accuracy or completeness — marketplaces re-render their pages and fields may move.
- Scraping public listings is legal in most jurisdictions, but comply with the target sites' terms of service. You are responsible for how you use the data.
- This Actor is batch-only (no standby mode): it starts, collects, and exits.
- Issues or feature requests: use the Actor's Issues tab, or open an issue on the repository.

# Actor input Schema

## `start_urls` (type: `array`):

Listing/search URLs on hatla2ee.com or opensooq.com to start scraping from.

## `max_items` (type: `integer`):

Upper limit on listings pushed per source (0 = unlimited). A run using both sources can return up to twice this.

## `max_requests_per_crawl` (type: `integer`):

Hard cap on pages fetched by the whole run — listing, pagination and detail pages combined (keeps cost predictable).

## `proxyConfiguration` (type: `object`):

Optional. Use Apify Proxy or your own proxy URLs if a source starts blocking runs.

## Actor input object example

```json
{
  "start_urls": [
    {
      "url": "https://www.hatla2ee.com/ar/car"
    },
    {
      "url": "https://eg.opensooq.com/en/cars"
    }
  ],
  "max_items": 50,
  "max_requests_per_crawl": 20,
  "proxyConfiguration": {
    "useApifyProxy": false
  }
}
```

# Actor output Schema

## `results` (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 = {
    "start_urls": [
        {
            "url": "https://www.hatla2ee.com/ar/car"
        },
        {
            "url": "https://eg.opensooq.com/en/cars"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("fourarms_4x4/mena-classifieds").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 = { "start_urls": [
        { "url": "https://www.hatla2ee.com/ar/car" },
        { "url": "https://eg.opensooq.com/en/cars" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("fourarms_4x4/mena-classifieds").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 '{
  "start_urls": [
    {
      "url": "https://www.hatla2ee.com/ar/car"
    },
    {
      "url": "https://eg.opensooq.com/en/cars"
    }
  ]
}' |
apify call fourarms_4x4/mena-classifieds --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,fourarms_4x4/mena-classifieds"
        }
    }
}
```

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/TzEMQGcheLSIarQNV/builds/fkYN9kHBfatWQFAYb/openapi.json
