# Algeria Jobs Scraper - Ouedkniss (`scraper_guru/algeria-jobs-scraper`) Actor

Scrape Algerian job listings from Ouedkniss. Extract titles, employers, wilayas, salaries, dates, skills, contracts, descriptions, and URLs for recruitment and job-market research.

- **URL**: https://apify.com/scraper\_guru/algeria-jobs-scraper.md
- **Developed by:** [LIAICHI MUSTAPHA](https://apify.com/scraper_guru) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 results

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

## Algeria Jobs Scraper - Ouedkniss

Scrape Algerian employment listings from [Ouedkniss](https://www.ouedkniss.com/emploi_offres?lang=fr), one of the country's largest classified marketplaces. Collect structured job data in French or Arabic for recruitment research, HR analytics, lead generation, and job-market monitoring.

### Features

- Collects job titles, companies, wilayas, locations, salaries, contracts, experience, education, dates, descriptions, skills, and canonical URLs.
- Supports French and Arabic listings.
- Follows result-page pagination with configurable limits.
- Uses browser rendering for dynamic Ouedkniss pages.
- Saves run statistics and diagnostic HTML snapshots when the source structure changes.
- Supports optional Apify Proxy configuration when direct requests are blocked.

### Use cases

- Build an Algeria job-market dataset for dashboards and analysis.
- Monitor hiring demand by wilaya, role, company, or skill.
- Create recruitment and B2B lead lists from public job postings.
- Track salary and contract signals across Algerian listings.
- Feed normalized job records into an HR or AI pipeline.

### Input

The default input starts from the Ouedkniss employment feed:

```json
{
  "startUrls": [
    {"url": "https://www.ouedkniss.com/emploi_offres/1?lang=fr"}
  ],
  "maxListings": 100,
  "maxPages": 5,
  "includeDetails": true,
  "maxConcurrency": 2,
  "proxyConfiguration": {"useApifyProxy": true}
}
```

`startUrls` accepts Ouedkniss employment or search pages. Set `maxListings` to `0` to collect every listing found on the selected pages. The default uses Apify Proxy because direct requests may time out; disable it only after confirming the source is reachable from your environment.

### Output

Each dataset item uses a stable, analysis-friendly structure:

```json
{
  "job_title": "Data Engineer",
  "company_name": "Example Algeria",
  "wilaya": "Alger",
  "location": "Alger",
  "salary": "150 000 DA",
  "contract_type": "CDI",
  "experience_level": "2 years",
  "education_level": "Engineering degree",
  "description": "Build reliable data pipelines.",
  "skills": ["python", "sql"],
  "date_posted": "2026-09-24",
  "job_url": "https://www.ouedkniss.com/annonce/emploi/example-123",
  "source_listing_url": "https://www.ouedkniss.com/emploi_offres?lang=fr",
  "source_language": "fr",
  "scraped_at": "2026-09-24T12:00:00.000Z"
}
```

The `overview` dataset view is ready for browsing and exports. Run metrics are saved under the `STATS` key in the default key-value store.

### How to use

1. Open the Actor in Apify Console.
2. Add an Ouedkniss employment or search URL, or use the default feed.
3. Set the maximum number of listings and pages.
4. Enable Apify Proxy if the source blocks direct traffic.
5. Start the run and export the dataset as JSON, CSV, or Excel.

#### Python

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("scraper_guru/algeria-jobs-scraper").call(run_input={
    "maxListings": 100,
    "maxPages": 5,
    "includeDetails": True
})

items = list(client.dataset(run["defaultDatasetId"]).iterate_items())
```

#### JavaScript

```javascript
import { Actor } from 'apify-client';

const client = new Actor({ token: process.env.APIFY_TOKEN });
const run = await client.actor('scraper_guru/algeria-jobs-scraper').call({
    maxListings: 100,
    maxPages: 5,
    includeDetails: true,
});

const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### Pricing

This Actor uses Apify pay-per-event pricing. Check the Actor page for the current per-result price and platform usage charges. The final cost depends on the number of records returned and whether detail pages are opened.

### Analyze a collected snapshot

After downloading the Actor dataset into `storage/datasets/default`, generate charts and reports with:

```bash
python analysis/analyze_jobs.py \
  --input storage/datasets/default \
  --output analysis/output
```

The analysis creates normalized CSV data, summary tables, PNG/SVG charts, a chart contact sheet, `market_report.md`, and Reddit/LinkedIn drafts. See [`analysis/README.md`](analysis/README.md) for the methodology and caveats.

### Data quality and limitations

Ouedkniss listings may be written in French, Arabic, or a mix of both. Salary, company, experience, and education fields are only populated when the publisher provides them. Site layout changes can affect extraction; failed or empty pages leave a diagnostic snapshot in the key-value store.

Use the data responsibly, follow Ouedkniss terms and applicable law, and respect privacy and contact preferences.

### FAQ

#### Does it scrape Arabic listings?

Yes. The crawler accepts Arabic pages and records a `source_language` field when Arabic text is detected.

#### Can I target a specific wilaya?

Pass an Ouedkniss employment search URL for the desired location in `startUrls`.

#### Why did a run return no records?

The site may have blocked the request, changed its markup, or returned an empty search. Enable Apify Proxy and inspect the saved snapshot and `STATS` record.

#### Does it open every job page?

By default, yes. Set `includeDetails` to `false` for a faster card-level collection.

#### Can I schedule recurring monitoring?

Yes. Create an Apify schedule and set a suitable interval for the source and your use case.

#### Can I export the results?

Yes. Use the dataset view or Apify API to export JSON, CSV, Excel, or RSS-compatible feeds.

### Support

For reproducible issues, include the run ID, input, `STATS` record, and the affected Ouedkniss URL when contacting the Actor author.

# Actor input Schema

## `startUrls` (type: `array`):

Optional Ouedkniss employment or search pages. Defaults to the French employment feed.

## `maxListings` (type: `integer`):

Maximum number of job records to return. Use 0 to collect all listings found on the selected pages.

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

Maximum number of Ouedkniss result pages to process per start URL.

## `includeDetails` (type: `boolean`):

Open each listing page to collect a fuller description and structured job metadata.

## `maxConcurrency` (type: `integer`):

Number of browser pages used in parallel. Lower values are gentler on the source website.

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

Optional. Enable an Apify Proxy if direct requests are blocked in your environment.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://www.ouedkniss.com/emploi_offres/1?lang=fr"
    }
  ],
  "maxListings": 20,
  "maxPages": 2,
  "includeDetails": true,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `jobs` (type: `string`):

The dataset containing extracted Ouedkniss job listings.

## `runStats` (type: `string`):

JSON record with crawl metrics.

## `debugSnapshots` (type: `string`):

HTML snapshots saved for pages whose structure needs review.

# 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 = {
    "startUrls": [
        {
            "url": "https://www.ouedkniss.com/emploi_offres/1?lang=fr"
        }
    ],
    "maxListings": 20,
    "maxPages": 2,
    "includeDetails": true,
    "maxConcurrency": 2,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("scraper_guru/algeria-jobs-scraper").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 = {
    "startUrls": [{ "url": "https://www.ouedkniss.com/emploi_offres/1?lang=fr" }],
    "maxListings": 20,
    "maxPages": 2,
    "includeDetails": True,
    "maxConcurrency": 2,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("scraper_guru/algeria-jobs-scraper").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 '{
  "startUrls": [
    {
      "url": "https://www.ouedkniss.com/emploi_offres/1?lang=fr"
    }
  ],
  "maxListings": 20,
  "maxPages": 2,
  "includeDetails": true,
  "maxConcurrency": 2,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call scraper_guru/algeria-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,scraper_guru/algeria-jobs-scraper"
        }
    }
}
```

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/t6jUFzI2X84hCgwl2/builds/wgEDXyg4D8fLQiVAV/openapi.json
