# Jiji Scraper — Africa Classifieds (NG, KE, GH, UG, TZ) (`logiover/jiji-africa-scraper`) Actor

Export classified adverts from Jiji across five African markets: title, description, price and currency, per-category attributes such as mileage, bedrooms or condition, region and area, seller name, rating and verification badges, plus every advert photo URL.

- **URL**: https://apify.com/logiover/jiji-africa-scraper.md
- **Developed by:** [Logiover](https://apify.com/logiover) (community)
- **Categories:** E-commerce, Real estate, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.50 / 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.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Jiji Scraper — Africa Classifieds (Nigeria, Kenya, Ghana, Uganda, Tanzania)

Jiji is the largest online classifieds network in Sub-Saharan Africa, and the volume is real: on the Nigerian site alone there are **420,000 home & garden adverts, 251,000 vehicle adverts, 216,000 electronics adverts, 67,000 cars, 24,000 houses for sale and 13,000 rentals** live right now. This Actor turns any of those categories — on any of five country sites — into a clean table with price, per-category attributes, location, seller and photos.

One Actor covers **Nigeria (jiji.ng), Kenya (jiji.co.ke), Ghana (jiji.com.gh), Uganda (jiji.ug) and Tanzania (jiji.co.tz)**, each with its own currency and regions, because the sites share one data contract.

### What you get

One row per advert, 37 columns:

| Group | Fields |
|---|---|
| Identity | `advertId`, `guid`, `url`, `title`, `description`, `status`, `source`, `country` |
| Pricing | `price`, `currency`, `priceLabel`, `pricePeriod` (e.g. "per month" on rentals) |
| Category | `category`, `categorySlug`, `categoryId`, `isJobAd` |
| Attributes | `condition`, `attributes` (object), `attributesText` |
| Location | `region`, `regionName`, `regionParent`, `regionSlug` |
| Seller | `sellerName`, `sellerId`, `sellerRating`, `sellerAvatar`, `canViewContacts` |
| Trust & promotion | `isVerifiedId`, `isInspected`, `isPopular`, `isPromoted`, `promotionPackage` |
| Media | `imageCount`, `mainImage`, `imageUrls` |
| Meta | `scrapedAt` |

**`attributes` is the column that makes this dataset useful.** Jiji stores a different attribute set per category, and this Actor keeps all of them — as a nested object that the platform flattens into its own CSV columns, and as a readable one-line string:

- a car: `Condition: Foreign Used | Transmission: Automatic | Mileage: 150000 km`
- a flat: `Property size: 250 sqm | Furnishing: Unfurnished | Bedrooms: 4 | Bathrooms: 4`
- a phone: `Condition: Brand New`

#### Sample row (Kenya, rentals)

```json
{
  "advertId": "54491233",
  "url": "https://jiji.co.ke/kiambu/houses-apartments-for-rent/4-bedroom-townhouse-....html",
  "title": "4 Bedroom Townhouse in Kiambu Road",
  "price": 380000,
  "currency": "KES",
  "priceLabel": "KSh 380,000",
  "pricePeriod": "per month",
  "category": "Houses & Apartments For Rent",
  "attributes": {
    "Property size": "250 sqm",
    "Furnishing": "Unfurnished",
    "Bedrooms": "4",
    "Bathrooms": "4"
  },
  "region": "Kiambu, Kiambu / Kiambu",
  "regionParent": "Kiambu",
  "sellerName": "Peter M Ndungu",
  "sellerRating": 4.8,
  "isVerifiedId": true,
  "imageCount": 11,
  "mainImage": "https://pictures-kenya.jijistatic.com/86703997_....jpg"
}
```

### Input

| Field | What it does |
|---|---|
| **Country** | Nigeria, Kenya, Ghana, Uganda or Tanzania. Each is a separate marketplace. |
| **Category** | The slug from the category URL. Verified on jiji.ng: `home-garden`, `vehicles`, `electronics`, `furniture`, `services`, `cars`, `mobile-phones`, `houses-apartments-for-sale`, `land-and-plots-for-sale`, `houses-apartments-for-rent`, `jobs`. |
| **Search term** | Optional free-text search across every category — overrides the category when set. |
| **Maximum adverts** | Stop after this many rows; roughly 23 adverts arrive per page. |
| **Proxy** | Residential, pinned automatically to the selected country. |

```json
{
  "market": "ng",
  "categorySlug": "cars",
  "maxResults": 1000,
  "proxyConfiguration": { "useApifyProxy": true, "apifyProxyGroups": ["RESIDENTIAL"] }
}
```

Searching instead of browsing:

```json
{ "market": "ke", "searchQuery": "toyota corolla", "maxResults": 500 }
```

### What it is good for

**Price benchmarking in markets with no official index.** Used-car and property prices across West and East Africa are not published anywhere reliable. A few thousand rows with `price`, `condition`, `Mileage` and `regionParent` produce a real price curve per model and per state — the input to a valuation tool, an insurance model or a trade-in calculator.

**Supply and demand intelligence.** `isPromoted` and `promotionPackage` reveal which sellers are paying for reach this week; `isPopular` and `isVerifiedId` separate serious sellers from noise. Run daily and the delta shows which categories are heating up.

**Dealer and merchant discovery.** `sellerId` is stable, so grouping a run by seller shows who is running a business rather than selling one item — a shortlist of active traders in a category, with rating and advert count attached. `sellerName` is filled where the seller trades under a name (about 15% of adverts in property, higher in vehicles and services).

**Product-catalogue and pricing data for e-commerce.** Electronics and phone categories carry brand, condition and price at a volume no marketplace API exposes, which is what makes them usable for repricing and for building a local catalogue.

**Cross-market comparison.** The same phone, the same car model, five countries and five currencies, in one schema — a comparison that normally means five separate scrapers.

### How it works

Jiji's own front end reads its listings from a JSON endpoint, and this Actor reads the same endpoint directly. That means no HTML parsing, no headless browser, and no breakage when the site is restyled — the result is fast, cheap and stable.

Each request is routed through a residential IP inside the target country, because each Jiji site serves its full result set only to local traffic.

Long runs are protected by the guards this Actor family shares:

- **A fresh IP on every retry**, since one 403 from one exit node says nothing about the next.
- **A failed page is skipped, not fatal**; three consecutive failures stop the run.
- **De-duplication by advert ID**, so promoted adverts repeated across pages are saved once.
- **A time budget** that stops the crawl while everything already collected is safely pushed.

Deep pagination is verified rather than assumed: pages 1, 15 and 40 of the same category return entirely distinct adverts.

### Cost and limits

Billing is per result, so cost follows rows saved rather than pages fetched. Store discounts apply on paid Apify plans.

- **Phone numbers are not included.** Jiji puts seller contacts behind a click that requires a session, and this Actor does not log in. `canViewContacts` tells you whether the advert exposes contacts at all; `sellerId` and the advert URL are what you use to reach a seller.
- Category slugs differ slightly between countries — copy the slug from the category URL on the site you are targeting.
- `condition` is a car/electronics attribute; property adverts have `Bedrooms` and `Furnishing` instead, all of which live in `attributes`.
- `sellerName` is present only where the seller publishes one; `sellerId` is always present.

### Legal

This Actor reads publicly listed adverts. It does not log in, does not bypass access controls, and does not touch contact details hidden behind authentication. Advert text and seller names may constitute personal data — process them with a lawful basis and honour deletion requests.

Not affiliated with, endorsed by, or connected to Jiji or its operators. The name is used only to identify the public source of the data.

# Actor input Schema

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

Which Jiji site to scrape. Each country is a separate marketplace with its own adverts, currency and regions.

## `categorySlug` (type: `string`):

Category slug, taken from the category URL on the site. Verified high-volume slugs on jiji.ng: home-garden (420k adverts), vehicles (251k), electronics (216k), furniture (134k), services (76k), cars (67k), mobile-phones (28k), houses-apartments-for-sale (24k), land-and-plots-for-sale (14k), houses-apartments-for-rent (13k), jobs. Ignored when a search term is given below.

## `searchQuery` (type: `string`):

Free-text search across every category, e.g. iphone, toyota corolla, generator, 3 bedroom. Leave empty to walk the category above instead.

## `maxResults` (type: `integer`):

Stop once this many adverts have been saved. Jiji returns roughly 23 adverts per page.

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

Each Jiji site answers properly only from inside its own country, so residential proxies are pinned to the selected market automatically.

## Actor input object example

```json
{
  "market": "ng",
  "categorySlug": "cars",
  "searchQuery": "iphone",
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}
```

# Actor output Schema

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

Every record collected in this run. Open the Dataset tab to browse, filter or export as JSON, CSV or Excel.

# 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 = {
    "market": "ng",
    "categorySlug": "cars",
    "maxResults": 100,
    "proxyConfiguration": {
        "useApifyProxy": true,
        "apifyProxyGroups": [
            "RESIDENTIAL"
        ]
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("logiover/jiji-africa-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 = {
    "market": "ng",
    "categorySlug": "cars",
    "maxResults": 100,
    "proxyConfiguration": {
        "useApifyProxy": True,
        "apifyProxyGroups": ["RESIDENTIAL"],
    },
}

# Run the Actor and wait for it to finish
run = client.actor("logiover/jiji-africa-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 '{
  "market": "ng",
  "categorySlug": "cars",
  "maxResults": 100,
  "proxyConfiguration": {
    "useApifyProxy": true,
    "apifyProxyGroups": [
      "RESIDENTIAL"
    ]
  }
}' |
apify call logiover/jiji-africa-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,logiover/jiji-africa-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/Ay9Oylxefk8fWAc5O/builds/O13EfRnG2BrJmDoOF/openapi.json
