# Djinni.co public jobs scraper (`codingfrontend/djinni-co-scraper`) Actor

Extracts public Djinni.co job listings from official search and detail pages with bounded requests. Access boundaries are reported without bypasses.

- **URL**: https://apify.com/codingfrontend/djinni-co-scraper.md
- **Developed by:** [Coding Frontned](https://apify.com/codingfrontend) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event and usage. You are charged both the fixed price for specific events and for Apify platform usage.

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

### What does this Actor do?

This Actor reads public pages on [Djinni.co](https://djinni.co/jobs/) and emits source-backed job records. It can construct an official public search from keyword, location, experience, English-level, and contract filters, or inspect supplied public Djinni URLs. It prefers standards-based `JobPosting` JSON-LD, checks public embedded page state, and supplements structured data with explicit `/jobs/...` links.

The source host is restricted to `djinni.co` and its public subdomains. The Actor does not log in, use credentials, call private APIs, solve CAPTCHAs, bypass WAFs, evade rate limits, or use a proxy configuration. If the source is empty, challenged, unavailable, or returns no explicit job fields, the Actor records a minimal diagnostic instead of inventing a vacancy.

### Why use this Actor?

Use it for a bounded snapshot of public Djinni developer vacancies in a research, hiring, or matching workflow. Normal rows have a stable source identifier or URL-derived ID, a public title, hiring company, provenance, and optional structured fields such as location, employment type, salary, dates, skills, and application links. Unpublished values are omitted. Nested contact evidence, raw HTML, inventory metadata, and crawler instrumentation are not emitted.

The run is deliberately predictable. `maxItems`, `maxPages`, and `maxRequests` cap work; response bytes and timeouts are bounded; transient statuses receive only a small retry budget; same-site next pages and duplicate listings are controlled; and optional detail requests share the global request budget.

### How to use

Run with the default input for a public Djinni jobs search. Set `keywords` or `location` for a focused search, or pass a `searchUrl` pointing to a public Djinni URL. Keep `includeDiagnostics` enabled during setup so access conditions are visible. Set `includeDetails` to `false` when only listing pages are needed.

For a local run from this directory:

```bash
npm ci
npm run check
apify run --purge --input-file .actor/input.json
```

### Input

```json
{
  "keywords": "Python",
  "location": "Remote",
  "maxItems": 20,
  "maxPages": 2,
  "maxRequests": 10,
  "includeDetails": true,
  "includeDiagnostics": true,
  "deduplicate": true,
  "timeoutSecs": 30,
  "maxRetries": 1
}
```

`searchUrl` and `startUrls` are optional public URL inputs; `sourceUrls`, `urls`, and singular `url` are accepted aliases. The default search is `https://djinni.co/jobs/`. `maxItems` limits normal rows; `maxPages` limits search pagination; and `maxRequests` is the hard cap across listing and detail pages. `requestDelayMs` and `maxResponseBytes` provide additional polite and resource bounds. `timeoutSecs` also accepts `requestTimeoutSecs` or `requestTimeoutMs` aliases. `userAgent` is an optional transparent HTTP label, not an identity or access credential.

### Output

A normal record resembles:

```json
{
  "jobId": "dj-42",
  "jobTitle": "Senior Python Engineer",
  "company": "Example Labs",
  "location": "Kyiv, UA",
  "workplaceType": "remote",
  "employmentType": "FULL_TIME",
  "description": "Build public platform services.",
  "datePosted": "2026-09-01T00:00:00.000Z",
  "salaryCurrency": "USD",
  "salaryMin": 60000,
  "salaryMax": 80000,
  "skills": ["Python", "Django"],
  "url": "https://djinni.co/jobs/dj-42/",
  "canonicalUrl": "https://djinni.co/jobs/dj-42/",
  "sourceUrl": "https://djinni.co/jobs/?keywords=Python",
  "pageUrl": "https://djinni.co/jobs/?keywords=Python",
  "sourceDomain": "djinni.co",
  "pageNumber": 1,
  "position": 1,
  "scrapedAt": "2026-09-10T00:00:00.000Z"
}
```

Download normal jobs and diagnostic rows from the Dataset tab. Normal job rows contain source-backed business and crawl-provenance fields; diagnostic rows use `recordType: "diagnostic"` and include `diagnosticType`, `errorCode`, `sourceUrl`, and `scrapedAt`. Internal extraction and transport metadata is not emitted in normal rows. `OUTPUT_SUMMARY` in the key-value store contains the status, request counts, page counts, retries, and bounded failure URLs.

### Data fields

| Field | Meaning |
| --- | --- |
| `jobId`, `jobTitle`, `company` | Public identity and hiring information. |
| `companyUrl`, `location`, `department` | Public organization and role context. |
| `workplaceType`, `employmentType` | Published work mode and contract type. |
| `description`, `skills` | Public listing content. |
| `datePosted`, `salaryCurrency`, `salaryMin`, `salaryMax` | Conservative structured fields. |
| `url`, `applyUrl` | Public job and application links. |
| `canonicalUrl`, `sourceDomain` | Stable URL identity and public source provenance. |
| `sourceUrl`, `pageUrl`, `pageNumber`, `position` | Crawl provenance. |
| `scrapedAt` | UTC normalization time. |
| `errorCode`, `error` | Minimal access or no-data diagnostic fields. |

### Pricing

Apify platform usage and any applicable plan charges are separate from this Actor. Actual cost depends on platform resources, run duration, request latency, and whether public detail pages are enabled. The Actor bounds its own request work but cannot guarantee a particular platform bill.

### Tips

Start with one page, a small item limit, and diagnostics enabled. Use a modest `requestDelayMs` for repeated snapshots. Save results if you need history because public listings, availability, and source markup change over time. A source challenge is useful monitoring information and should not be treated as an empty market.

### FAQ and disclaimers

**Why did I receive `source_challenge`?** Djinni may have returned a security challenge, HTTP 403/429, or another access boundary. The Actor stops within its limits and does not bypass it.

**Does this Actor access private jobs or contact data?** No. It reads public job fields only and does not emit contact harvesting fields.

**Are missing values inferred?** No. Optional values are included only when published in public structured data, embedded state, or a conservative public link.

Respect Djinni's terms, applicable law, robots guidance, and rate limits. This Actor is for lawful public-data use and does not guarantee completeness, freshness, availability, or continued compatibility with source markup.

# Actor input Schema

## `searchUrl` (type: `string`):

Optional official public Djinni search URL.

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

Optional official public search or job URLs.

## `sourceUrls` (type: `array`):

Alias for public Djinni search or job URLs.

## `urls` (type: `array`):

Alias for public Djinni search or job URLs.

## `url` (type: `string`):

Alias for one public Djinni search or job URL.

## `keywords` (type: `string`):

Optional public skill or title keyword.

## `experience` (type: `string`):

Optional public experience filter.

## `englishLevel` (type: `string`):

Optional public English-level filter.

## `location` (type: `string`):

Optional public location filter.

## `contractType` (type: `string`):

Optional public contract filter.

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

Maximum normal job records emitted.

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

Maximum public search pages inspected.

## `maxRequests` (type: `integer`):

Hard cap across search and optional detail requests.

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

Fetch public job detail pages while the request budget allows.

## `includeDiagnostics` (type: `boolean`):

Emit minimal access and no-data rows.

## `deduplicate` (type: `boolean`):

Suppress repeated source IDs or URLs.

## `requestDelayMs` (type: `integer`):

Optional delay between requests.

## `timeoutSecs` (type: `integer`):

Maximum wait per public request.

## `requestTimeoutSecs` (type: `integer`):

Alias for timeoutSecs.

## `requestTimeoutMs` (type: `integer`):

Alias for timeoutSecs in milliseconds.

## `maxRetries` (type: `integer`):

Bounded transient/network retries.

## `maxResponseBytes` (type: `integer`):

Maximum accepted HTML response size.

## `userAgent` (type: `string`):

Optional transparent HTTP user-agent label.

## Actor input object example

```json
{
  "maxItems": 20,
  "maxPages": 2,
  "maxRequests": 10,
  "includeDetails": true,
  "includeDiagnostics": true,
  "deduplicate": true,
  "requestDelayMs": 0,
  "timeoutSecs": 30,
  "maxRetries": 1,
  "maxResponseBytes": 2000000
}
```

# Actor output Schema

## `dataset` (type: `string`):

Normal jobs and minimal diagnostics.

## `summary` (type: `string`):

Structured OUTPUT_SUMMARY record.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("codingfrontend/djinni-co-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("codingfrontend/djinni-co-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 '{}' |
apify call codingfrontend/djinni-co-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,codingfrontend/djinni-co-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/aV2l934irwlEhS8A1/builds/wMOpYagakUyhtEaRV/openapi.json
