# Djinni Jobs Scraper (`automation-lab/djinni-tech-jobs-scraper`) Actor

Search public Djinni tech vacancies and export structured jobs with employer, salary signal, location or remote status, experience, English level, description, activity counts, and canonical URL.

- **URL**: https://apify.com/automation-lab/djinni-tech-jobs-scraper.md
- **Developed by:** [Stas Persiianenko](https://apify.com/automation-lab) (community)
- **Categories:** Jobs
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.55 / 1,000 item extracteds

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#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

## Djinni Jobs Scraper

Extract public **Djinni jobs** into clean records for recruiting, sourcing, and labor-market monitoring. Search by role or skill, follow Djinni search-page filters, and export job title, employer, salary signal, location, remote status, experience, English level, description context, activity counts, and canonical URL.

The Actor uses Djinni's server-rendered public vacancy pages. It does not require a Djinni account, a browser, or a paid proxy.

### What can you do with this Actor?

- Build a current feed of tech vacancies for one or more skills.
- Compare salary signals, experience requirements, and English levels.
- Find roles that Djinni marks as remote.
- Schedule recurring runs and compare stable `jobId` values downstream.
- Export job data to JSON, CSV, Excel, Google Sheets, a database, or an ATS workflow.

### Who is it for?

Recruiters can create targeted vacancy lists. Talent teams can monitor employer activity. Labor-market analysts can compare role, geography, English, and experience signals. Developers can feed normalized vacancy data into dashboards and automations without maintaining an HTML parser.

### Data extracted

| Field | Meaning |
| --- | --- |
| `jobId` | Stable Djinni vacancy identifier |
| `title`, `employer` | Advertised role and employer |
| `salaryText` | Public salary amount when displayed |
| `salarySignal` | Djinni's relative `$` to `$$$$` salary signal |
| `location`, `remote` | Hiring region and source remote flag |
| `experience`, `experienceYears` | Displayed and parsed experience requirement |
| `englishLevel` | English requirement such as B1 or B2 |
| `category` | Job category shown in the listing |
| `description` | Full plain-text description context available on the search page |
| `views`, `applications` | Public engagement counts when shown |
| `postedText`, `postedAt` | Displayed age and parsed posting timestamp |
| `jobUrl` | Canonical public vacancy URL |
| `sourceSearchUrl`, `scrapedAt` | Provenance and extraction timestamp |

Fields can be `null` when Djinni does not disclose the value.

### How to get started

1. Open the Actor input.
2. Add one or more role or skill names under **Job keywords**.
3. Optionally add a public `https://djinni.co/jobs/` search URL containing Djinni filters.
4. Enable **Remote jobs only** if needed.
5. Choose a maximum number of jobs.
6. Click **Start** and open the default dataset when the run finishes.

A useful first input is:

```json
{
  "keywords": ["JavaScript"],
  "maxItems": 10
}
```

### Input parameters

#### `keywords`

Up to 20 tech roles or skills. Each value becomes a Djinni `primary_keyword` search. Results are deduplicated across searches.

#### `startUrls`

Optional public Djinni jobs search URLs. Use these when you have already selected source-side filters on Djinni. Other domains and job-detail URLs are rejected.

#### `remoteOnly`

Keeps only records that Djinni marks as remote. This filter is applied equally to keyword searches and supplied search URLs.

#### `maxItems`

Maximum unique records saved across all input searches, from 1 to 5,000. Pagination stops as soon as this limit is reached.

#### `maxRequestRetries`

Number of bounded retries for temporary network, rate-limit, or server failures, from 0 to 4. Permanent errors are not retried blindly.

### Output example

```json
{
  "jobId": "846751",
  "title": "Senior Frontend Engineer, Progressive Web Apps",
  "employer": "Genius Match",
  "salaryText": null,
  "salarySignal": "$$$$",
  "location": "EU",
  "remote": true,
  "experience": "7 years of experience",
  "experienceYears": 7,
  "englishLevel": "B2",
  "category": "Education",
  "description": "Our client is the leader in the Early Childhood Education sector...",
  "views": 304,
  "applications": 29,
  "postedText": "2d",
  "postedAt": "2026-09-04T17:00:00",
  "jobUrl": "https://djinni.co/jobs/846751-senior-frontend-engineer-progressive-web-apps/",
  "sourceSearchUrl": "https://djinni.co/jobs/?primary_keyword=JavaScript",
  "scrapedAt": "2026-09-06T20:38:23.401Z"
}
```

Values change as vacancies and engagement counts change.

### How much does it cost to extract Djinni jobs?

Pricing uses one small start charge plus a per-job event. Per-job rates decrease by Apify account tier. The exact active prices are shown in the Actor's pricing panel before every run.

As a simple estimate, multiply the displayed per-job event price by the requested result count and add the displayed start event. The Actor uses direct HTTP at 256 MB and has no automatic residential-proxy or browser fallback, keeping platform usage predictable.

### Recurring monitoring workflow

Schedule the same input daily or weekly. Store `jobId`, `postedAt`, and selected fields in your destination. Compare each new dataset with the prior snapshot to identify new jobs, removed jobs, or changed public signals. The Actor produces current snapshots; it does not persist history or send alerts itself.

### Spreadsheet and database export

In the run dataset, choose CSV, Excel, JSON, XML, or RSS. For ongoing pipelines, read the dataset API or connect an Apify integration. Use `jobId` as the source identity and `scrapedAt` as the observation time.

### API with cURL

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/automation-lab~djinni-tech-jobs-scraper/runs?token=$APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"keywords":["DevOps"],"maxItems":25}'
```

Add `waitForFinish=120` when a synchronous workflow is appropriate, then read the run's default dataset.

### API with JavaScript

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

const client = new ApifyClient({ token: process.env.APIFY_TOKEN });
const run = await client.actor('automation-lab/djinni-tech-jobs-scraper').call({
  keywords: ['Python'],
  remoteOnly: true,
  maxItems: 20,
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items);
```

### API with Python

```python
import os
from apify_client import ApifyClient

client = ApifyClient(os.environ['APIFY_TOKEN'])
run = client.actor('automation-lab/djinni-tech-jobs-scraper').call(run_input={
    'keywords': ['Data Engineer'],
    'maxItems': 20,
})
items = client.dataset(run['defaultDatasetId']).list_items().items
print(items)
```

### Use with MCP and AI agents

Add the Apify MCP server to Claude Code:

```bash
claude mcp add --transport http apify \
  "https://mcp.apify.com?tools=automation-lab/djinni-tech-jobs-scraper"
```

For **Claude Desktop**, **Cursor**, or **VS Code**, add this MCP JSON configuration:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=automation-lab/djinni-tech-jobs-scraper"
    }
  }
}
```

Example prompts:

- “Run the Djinni Jobs Scraper for JavaScript and return 20 jobs grouped by English level.”
- “Collect remote Python roles from Djinni and summarize employer and experience patterns.”
- “Export current DevOps vacancies with salary signals and canonical URLs.”

### Reliability and limits

The Actor validates hosts and paths, checks response status and content type, deduplicates stable IDs, and retries only transient failures with bounded backoff. If Djinni returns an unexpected page shape, the run fails instead of silently producing a misleading empty dataset.

Djinni can change its public HTML or available filters. Results reflect the public pages visible at run time. A keyword may return broader matching jobs according to Djinni's own search behavior. The Actor does not apply, contact employers, bypass login, or recover historical vacancies.

### Troubleshooting

#### Why are fewer jobs returned than `maxItems`?

The source may have fewer matching public vacancies, duplicate jobs may appear across searches, or `remoteOnly` may filter records. `maxItems` is a ceiling, not a guaranteed count.

#### Why is salary null?

Many vacancies show only Djinni's relative salary signal. Use `salarySignal` for that source-provided indicator; `salaryText` remains null unless a public amount is shown in the card.

#### Why did the run fail on my URL?

Only HTTPS Djinni `/jobs/` search URLs are accepted. Open the filtered jobs page on Djinni and copy that search URL rather than a company, login, or individual job URL.

### Legality and responsible use

Scrape only public data for legitimate recruiting, research, and analytics purposes. Follow Djinni's terms, applicable privacy and employment laws, and your organization's data-retention rules. Avoid profiling individuals, discriminatory hiring decisions, excessive schedules, or unsolicited outreach. You are responsible for how exported data is stored and used.

### Related Actors

For broader regional hiring research, combine this source-specific feed with other public job-board Actors from [automation-lab on Apify](https://apify.com/automation-lab). Keep each source attributed by its canonical URL and source-specific ID.

### FAQ

#### Does it require a Djinni login?

No. It extracts public vacancy search pages only.

#### Does it use a proxy or browser?

No automatic proxy or browser mode is enabled. The current implementation uses lightweight direct HTTP requests.

#### Can I use a scheduled Actor task?

Yes. Save the exact input as an Apify Task and attach a schedule. Compare datasets downstream by `jobId`.

#### Can it return JSON, CSV, or Excel?

Yes. Apify datasets expose all of those export formats without changing Actor input.

#### Does it send alerts or retain change history?

No. Use schedules, webhooks, integrations, or your own database to build that workflow around the current snapshot.

# Actor input Schema

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

Tech roles or skills to search on Djinni, such as JavaScript, Python, or DevOps.

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

Optional public https://djinni.co/jobs/ search URLs. Existing query filters and pagination are preserved.

## `remoteOnly` (type: `boolean`):

Keep only vacancies marked as remote by Djinni.

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

Maximum number of unique job records to save across all searches.

## `maxRequestRetries` (type: `integer`):

Retries for temporary network, rate-limit, or server failures.

## Actor input object example

```json
{
  "keywords": [
    "JavaScript"
  ],
  "startUrls": [
    {
      "url": "https://djinni.co/jobs/?primary_keyword=Python"
    }
  ],
  "remoteOnly": false,
  "maxItems": 20,
  "maxRequestRetries": 2
}
```

# Actor output Schema

## `overview` (type: `string`):

Default dataset containing titles, employers, salary signals, location and remote status, experience, English level, descriptions, and canonical job URLs.

# 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": [
        "JavaScript"
    ],
    "startUrls": [
        {
            "url": "https://djinni.co/jobs/?primary_keyword=Python"
        }
    ],
    "maxItems": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("automation-lab/djinni-tech-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 = {
    "keywords": ["JavaScript"],
    "startUrls": [{ "url": "https://djinni.co/jobs/?primary_keyword=Python" }],
    "maxItems": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("automation-lab/djinni-tech-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 '{
  "keywords": [
    "JavaScript"
  ],
  "startUrls": [
    {
      "url": "https://djinni.co/jobs/?primary_keyword=Python"
    }
  ],
  "maxItems": 20
}' |
apify call automation-lab/djinni-tech-jobs-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,automation-lab/djinni-tech-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/QKNRsvwhkMrLrOUD0/builds/9BBqfT2607dajBIim/openapi.json
