# Pracuj.pl Scraper | Poland Job Offers + Salaries (`haketa/pracuj-scraper`) Actor

Pracuj.pl scraper & API for Poland job offers: search by keyword, city and filters (contract, work mode, seniority, salary) and export title, company, salary, location, remote status, coordinates and apply URL. Polish job-market data and recruitment leads — fast, no login.

- **URL**: https://apify.com/haketa/pracuj-scraper.md
- **Developed by:** [Haketa](https://apify.com/haketa) (community)
- **Categories:** Jobs, Lead generation
- **Features:** Limited permissions
- **Stats:** 4 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.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/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

## Pracuj.pl Scraper — Poland Job Offers, Salaries & Apply URLs

[![Apify Actor](https://img.shields.io/badge/Apify-Actor-orange?logo=apify)](https://apify.com/haketa/pracuj-scraper)
[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://apify.com/haketa/pracuj-scraper)
[![Data Format](https://img.shields.io/badge/Data-JSON%20%7C%20CSV%20%7C%20Excel-blue)](#-output)
[![Pagination](https://img.shields.io/badge/Pagination-1%2C000%2B%20Unlocked-brightgreen)](#-pagination--scale)
[![Proxy Support](https://img.shields.io/badge/Proxy-Datacenter%20\(PL%20Fallback\)-success)](#-input)

> **Scrape Pracuj.pl — Poland's #1 job board — into clean, structured data: job title, company, parsed salary, seniority, contract type, work mode, every location, coordinates and the direct apply URL. No login, no code, no captcha.**

Export to **JSON, CSV, Excel, or API**.

> Built for **recruitment agencies, headhunters, job boards & aggregators, HR-tech and salary-benchmarking teams, market researchers, and B2B sales teams** who need live Polish labour-market data without copy-pasting from a browser.

***

### ⚡ At a glance

| Feature | Details |
| :--- | :--- |
| **Target Website** | [pracuj.pl](https://www.pracuj.pl) (Poland #1 Job Portal) |
| **Search Capabilities** | Keywords, Polish cities, contract types, work modes, seniority levels |
| **Pagination Limit** | **1,000+ Unlocked** (`maxPagesPerSearch: 0` for unlimited multi-page traversal) |
| **Salary Extraction** | Parsed `salaryMin`, `salaryMax`, currency (PLN/EUR), period, and gross/net |
| **Locations & Remote** | Full Polish addresses, latitude/longitude, and remote/hybrid work badges |
| **Proxy Requirement** | Datacenter Proxy default (auto-escalates to Polish residential if blocked) |
| **Average Speed** | 50 offers per page (~500 offers in ~30–45 seconds) |
| **Output Formats** | JSON, CSV, Excel (XLSX), XML, HTML Table, RSS |

***

### 🔎 Why scrape Pracuj.pl?

[Pracuj.pl](https://www.pracuj.pl/) is the dominant job board in Poland — the first place most Polish employers post a vacancy, and the first place candidates look. That makes it the single richest public source of **Polish job-market data**: who is hiring, for which roles, in which cities, under which contract, at what salary, and how fresh the posting is.

The problem is that this data lives behind a search form, spread across thousands of paginated result pages, with salaries shown as free-text blobs ("5 300–5 800 zł brutto / mies.") and locations buried inside each card. Collecting it by hand — page by page, offer by offer — is slow, error-prone and impossible to keep current.

This **Pracuj.pl scraper** does it for you. Give it a keyword (and, optionally, a city and filters) and it reads Pracuj's live listing feed, paginates through the full result set, parses each offer into a tidy row, de-duplicates on the stable offer ID, and hands you a clean dataset you can export or pipe straight into your stack.

**Common reasons people scrape Pracuj.pl:**

- Build a **live feed of open roles** by keyword, city and seniority for a recruitment desk or ATS.
- **Benchmark salaries** across roles, cities, seniority and work mode using parsed pay bands.
- Measure **hiring demand** and the remote-work share across industries over time.
- Spot companies **actively hiring** in your niche and turn them into warm **B2B leads**.
- Power a **Polish job board or aggregator** with structured offers and direct apply links.
- Track **competitor postings** and how long roles stay on the market.

***

### ✨ What this Pracuj.pl scraper does

- 🇵🇱 **Searches all of Pracuj.pl** — any keyword (`python`, `sprzedawca`, `księgowa`, `kierowca`, `sales manager`) across Poland, or narrowed to a single city. Pass **multiple keywords** and each is searched separately and merged.
- 🔁 **Unlocked 1,000+ deep pagination** — walks the listing feed 50 offers per page until your `maxItems` limit is reached, returning hundreds to thousands of de-duplicated offers per run.
- 🏷️ **Rich, structured fields** — for every offer you get the **job** (`jobTitle`, `seniority`, `contractTypes`, `workModes`, `workSchedules`, `isRemote`, `description`, `aiSummary`), the **company** (`companyName`, `companyId`, `companyLogoUrl`, `companyProfileUrl`), the **salary** (`salaryText`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryGrossNet`), the **location** (`locations`, `isWholePoland`, `latitude`, `longitude`), the **dates** (`publishedAt`, `firstPublishedAt`, `expiresAt`) and the **meta** (`offerId`, `groupId`, `url`, `allOfferUrls`, promotion / one-click-apply / optional-CV flags).
- 💰 **Parsed salary bands** — when the employer publishes pay, the raw text is parsed into numeric `salaryMin` / `salaryMax`, plus currency, period and gross/net — not just a string.
- 🧭 **Combinable filters** — contract type, work mode, seniority level, `salaryOnly`, and "posted within N days", all applied server-side.
- 📍 **Every location** — a role posted in several cities returns all of them, with coordinates for the primary location for mapping.
- 🔗 **Direct apply links** — a deep link per offer (and `allOfferUrls` for multi-city postings), ready to send or store.
- 🧾 **Optional full descriptions** — flip on `scrapeDetails` to fetch each offer's long description; leave it off for fast, low-cost runs since the search feed already includes an AI summary.
- 📤 **Export anywhere** — JSON, CSV, Excel, HTML/XML, or straight from the **Pracuj.pl API** into Sheets, Airtable, a dashboard or a webhook.
- ⚡ **Fast & reliable** — pure-HTTP over datacenter proxies with automatic escalation to **Polish residential** proxies only if a block is detected.

***

### 🎯 Use cases

- **Recruitment agencies & headhunters** — keep a live, filterable feed of open roles by keyword, city and seniority; prospect companies that are actively hiring.
- **Job boards & aggregators** — syndicate Polish offers with full structured fields and apply links, kept fresh with scheduled runs and offer-ID de-duplication.
- **HR-tech & salary benchmarking** — analyse parsed salary bands by role, seniority, city and work mode to power pay reports and compensation tools.
- **Market & labour-market research** — track hiring demand, remote-work adoption and sector trends across Poland.
- **B2B sales & lead generation** — companies hiring for a role you sell into are warm leads; capture their names, logos and profile URLs.
- **Data teams & analysts** — feed clean, analysis-ready job data into a warehouse, notebook or BI dashboard.
- **Relocation & talent-mobility services** — surface roles by city, work mode and salary for candidates moving to Poland.

***

### 📥 Input parameters

Enter one or more keywords, optionally a city and filters, then press **Start**. Nothing is required — leave keywords empty for a nationwide sample.

| Parameter | Type | Default | Description |
| :--- | :--- | :--- | :--- |
| `keywords` | Array | `["python"]` | Job keywords, e.g. `["python", "accountant"]`. Each is searched separately. Empty = nationwide sample. |
| `location` | String | `""` | Optional Polish city or area, e.g. `warszawa`, `kraków`, `wrocław`. Applies to every keyword. |
| `contractTypes` | Select (multi) | `[]` | Filter by contract: `employment`, `b2b`, `mandate`, `task`, `replacement`, `agency`. |
| `workModes` | Select (multi) | `[]` | Filter by work mode: `remote`, `hybrid`, `office`, `mobile`. |
| `seniorityLevels` | Select (multi) | `[]` | Filter by seniority: `trainee`, `junior`, `mid`, `senior`, `expert`, `manager`. |
| `salaryOnly` | Boolean | `false` | Return only job offers that publish a salary. |
| `postedWithinDays` | Select | `"0"` | Any time / `1` / `3` / `7` / `14` / `30` days. |
| `startUrls` | Array | `[]` | Advanced: paste Pracuj.pl search URLs (e.g. `https://www.pracuj.pl/praca/java;kw/warszawa;wp`). |
| `scrapeDetails` | Boolean | `false` | Also visit each offer page for the full description (slower; one request per offer). |
| `maxItems` | Integer | `100` | Max offers across all keywords. `0` = unlimited. |
| `maxPagesPerSearch` | Integer | `0` | Cap pages per keyword (50 offers/page). `0` = auto/unlimited (governed by `maxItems`). |
| `requestDelay` | Integer | `400` | Delay between requests in ms (300–800 keeps runs smooth). |
| `proxyConfiguration` | Object | `{ "useApifyProxy": true }` | Datacenter by default; auto-escalates to PL residential if a block is detected. |

#### Example input configuration

```json
{
  "keywords": ["python", "data engineer"],
  "location": "warszawa",
  "workModes": ["remote", "hybrid"],
  "seniorityLevels": ["mid", "senior"],
  "salaryOnly": true,
  "maxItems": 150,
  "maxPagesPerSearch": 0,
  "proxyConfiguration": { "useApifyProxy": true }
}
```

***

### 📤 Output dataset

Each job offer is one row in the dataset.

#### Sample output item

```json
{
  "offerId": "1005189904",
  "groupId": "c8180000-56be-0050-3cc1-08df337915b3",
  "jobTitle": "Sprzedawca - Lada Tradycyjna (m/k)",
  "companyName": "Biedronka (Jeronimo Martins Polska S.A.)",
  "companyId": "921",
  "companyProfileUrl": "https://pracodawcy.pracuj.pl/company/921",
  "companyLogoUrl": "https://logos.gpcdn.pl/loga-firm/921/402b0000-56be-0050-bd29-08de187e6eb2_280x280.png",
  "salaryText": "5 300–5 800 zł brutto / mies.",
  "salaryMin": 5300,
  "salaryMax": 5800,
  "salaryCurrency": "PLN",
  "salaryPeriod": "month",
  "salaryGrossNet": "gross",
  "seniority": "Pracownik fizyczny / Pracowniczka fizyczna",
  "seniorityList": ["Pracownik fizyczny / Pracowniczka fizyczna"],
  "contractTypes": ["Umowa o pracę"],
  "workModes": ["Praca stacjonarna"],
  "workSchedules": ["Pełny etat", "Część etatu"],
  "isRemote": false,
  "locations": ["Olsztyn, Sielska 12", "Olsztyn, Towarowa 16"],
  "isWholePoland": false,
  "latitude": 53.768467,
  "longitude": 20.430515,
  "publishedAt": "2026-11-01T20:48:01.673Z",
  "firstPublishedAt": "2026-10-29T20:48:01.673Z",
  "expiresAt": "2026-11-28T22:59:59Z",
  "description": "Twój zakres obowiązków: obsługa klienta na ladzie tradycyjnej, wykładanie towaru…",
  "aiSummary": "Obsługa klientów na ladzie tradycyjnej, gotowość do pracy fizycznej na 3 zmiany, benefity finansowe i medyczne…",
  "isSuperOffer": true,
  "isOneClickApply": false,
  "isOptionalCv": false,
  "offerCount": 2,
  "allOfferUrls": [
    "https://www.pracuj.pl/praca/sprzedawca-lada-tradycyjna-m-k-olsztyn-sielska-12,oferta,1005189904"
  ],
  "url": "https://www.pracuj.pl/praca/sprzedawca-lada-tradycyjna-m-k-olsztyn-sielska-12,oferta,1005189904",
  "searchKeyword": "sprzedawca",
  "searchLocation": null,
  "scrapedAt": "2026-11-10T12:55:00.000Z"
}
```

***

#### Output field reference

##### 🧑‍💼 Job fields

| Field | Type | Coverage | Description |
| :--- | :--- | :--- | :--- |
| `jobTitle` | String | 🟢 High (100%) | Position title |
| `seniority` | String | 🟢 High (98%) | Seniority level as joined string |
| `seniorityList` | Array | 🟢 High (98%) | Seniority levels as string array |
| `contractTypes` | Array | 🟢 High (100%) | Contract types (umowa o pracę, B2B, zlecenie…) |
| `workModes` | Array | 🟢 High (100%) | Work mode(s) (Praca zdalna, hybrydowa, stacjonarna) |
| `isRemote` | Boolean | 🟢 High (100%) | Boolean remote work allowed flag |
| `workSchedules` | Array | 🟢 High (100%) | Full-time / part-time availability |
| `description` | String | 🟢 High (99%) | Short job description from the listing |
| `aiSummary` | String | 🟢 High (95%) | Pracuj's AI-generated summary of key responsibilities |
| `descriptionFull` | String | 🟡 Conditional | Long description (only when `scrapeDetails` is enabled) |

##### 💰 Salary fields

| Field | Type | Coverage | Description |
| :--- | :--- | :--- | :--- |
| `salaryText` | String | 🟡 Conditional (45%) | Raw salary text (e.g. `12 000 - 18 000 zł brutto / mies.`) |
| `salaryMin` | Integer | 🟡 Conditional (45%) | Parsed numeric minimum compensation band |
| `salaryMax` | Integer | 🟡 Conditional (45%) | Parsed numeric maximum compensation band |
| `salaryCurrency` | String | 🟡 Conditional (45%) | Currency (`PLN`, `EUR`, `USD`) |
| `salaryPeriod` | String | 🟡 Conditional (45%) | Pay frequency (`month`, `hour`, `year`, `day`) |
| `salaryGrossNet` | String | 🟡 Conditional (45%) | Tax basis (`gross` or `net`) |

##### 🏢 Company & location fields

| Field | Type | Coverage | Description |
| :--- | :--- | :--- | :--- |
| `companyName` | String | 🟢 High (100%) | Hiring employer or recruitment agency name |
| `companyId` | String | 🟢 High (100%) | Stable numeric employer ID on Pracuj.pl |
| `companyProfileUrl` | String | 🟢 High (100%) | Employer profile page URL on Pracuj |
| `companyLogoUrl` | String | 🟢 High (98%) | Company logo image CDN URL |
| `locations` | Array | 🟢 High (100%) | All cities and street addresses where role is posted |
| `isWholePoland` | Boolean | 🟢 High (100%) | Whether role accepts applicants nationwide |
| `latitude` | Float | 🟡 Conditional (65%) | Coordinate latitude of primary work address |
| `longitude` | Float | 🟡 Conditional (65%) | Coordinate longitude of primary work address |

##### 🔗 Meta fields

| Field | Type | Coverage | Description |
| :--- | :--- | :--- | :--- |
| `offerId` | String | 🟢 High (100%) | Primary unique offer ID (natural dedup key) |
| `groupId` | String | 🟢 High (100%) | Offer group GUID |
| `publishedAt` | String | 🟢 High (100%) | Most recent publish timestamp (ISO 8601) |
| `firstPublishedAt` | String | 🟢 High (100%) | Initial publication date (tracks time-on-market) |
| `expiresAt` | String | 🟢 High (100%) | Posting expiration timestamp |
| `url` | String | 🟢 High (100%) | Canonical direct URL to apply on Pracuj.pl |
| `allOfferUrls` | Array | 🟢 High (100%) | URLs for all multi-city locations of this offer |
| `scrapedAt` | String | 🟢 High (100%) | ISO 8601 UTC timestamp of data collection |

***

### 📊 Comparison: Why use this Actor?

| Feature | Manual Search | Custom Cheerio Scraper | Pracuj.pl Scraper |
| :--- | :--- | :--- | :--- |
| **Data Gateway** | Browser HTML rendering | Fragile DOM selectors | **Direct gateway JSON API** |
| **Salary Parsing** | Raw text string | Regular expression hacks | **Structured min/max/PLN/period** |
| **Multi-Location Roles** | 1 click per city | Fails on sub-offer arrays | **Extracts all addresses + GPS** |
| **Pagination Handling** | Manual pagination clicks | Stalls on pagination limits | **1,000+ Unlocked** (`maxPages: 0`) |
| **Anti-Bot Resilience** | Captchas on volume | Blocked by WAF | **Datacenter + PL Residential auto-escalate** |
| **Deduplication** | Manual Excel dedup | High duplicate error rate | **0 duplicate guarantee (`offerId`)** |

***

### 💻 Developer & API integrations

You can trigger this actor and retrieve structured recruitment datasets programmatically using Apify's API clients or cURL.

#### Python integration

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_APIFY_TOKEN")

run_input = {
    "keywords": ["devops", "cloud architect"],
    "location": "warszawa",
    "contractTypes": ["b2b"],
    "salaryOnly": True,
    "maxItems": 200,
    "maxPagesPerSearch": 0,
}

run = client.actor("haketa/pracuj-scraper").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(f"{item['jobTitle']} @ {item['companyName']}: {item['salaryText']} -> {item['url']}")
```

#### Node.js integration

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

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });

const input = {
    keywords: ['frontend developer'],
    workModes: ['remote'],
    maxItems: 150,
    maxPagesPerSearch: 0,
};

const run = await client.actor('haketa/pracuj-scraper').call(input);
const { items } = await client.dataset(run.defaultDatasetId).listItems();

console.log(`Scraped ${items.length} Polish tech offers from Pracuj.pl.`);
items.forEach(o => console.log(`${o.jobTitle} - ${o.salaryText || 'Undisclosed'} [${o.locations.join(', ')}]`));
```

#### cURL API call

```bash
curl "https://api.apify.com/v2/acts/haketa~pracuj-scraper/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "keywords": ["kierowca"],
    "location": "kraków",
    "maxItems": 100,
    "maxPagesPerSearch": 0
  }'
```

***

### 🔁 Pagination & scale

The scraper paginates Pracuj's listing feed automatically, **50 offers per page**, advancing `pn` (page number) until it hits your `maxItems` limit, the per-keyword `maxPagesPerSearch` cap, or the end of the result set. Every offer is de-duplicated on its stable `offerId` (falling back to `groupId`/`url`), so you never get the same posting twice.

- **Set `maxPagesPerSearch: 0` for auto-pagination**: Leaving `maxPagesPerSearch: 0` allows the pagination loop to continue unimpeded until `maxItems` is satisfied.
- **Deep category sweeps**: Enter `maxItems: 1000` or higher to extract comprehensive regional datasets.
- **Deduplication guarantee**: 100% verified 0 duplicate items across multiple pages and multi-city listings.

***

### 💡 Pro tips for best results

- **Unlock full pagination**: Keep `maxPagesPerSearch: 0` (the default) so the actor continuously retrieves pages until reaching your requested `maxItems`.
- **Target salary benchmarking**: Set `salaryOnly: true` when doing compensation studies to filter out offers without stated compensation bands.
- **Monitor time on market**: Compare `firstPublishedAt` with `publishedAt` to identify long-standing hard-to-fill vacancies.
- **Fast prefill runs**: Keep `scrapeDetails: false` (the default) to scrape 100+ offers in under 15 seconds.

***

### ⚠️ Limitations & considerations

- **Disclosed Salaries**: Polish employers disclose salaries on approximately 40–50% of listings. Use `salaryOnly: true` if you strictly require compensation figures.
- **Per-Offer Descriptions**: Full long descriptions require visiting individual offer pages. Turning on `scrapeDetails` increases execution duration.

***

### ❓ Frequently Asked Questions

**How does pagination work past 1,000 items?**
With `maxPagesPerSearch: 0`, the scraper requests consecutive pages of 50 items each until `maxItems` is satisfied or all matching positions are exhausted.

**Do I need Polish residential proxies?**
No. Datacenter proxies are used by default and are completely sufficient for the massachusetts gateway. The actor includes automatic failover to Polish residential proxies if any block is encountered.

**Does it extract direct application links?**
Yes. Each record includes the canonical direct URL to the job listing on Pracuj.pl.

**What formats are available for export?**
JSON, CSV, Excel (XLSX), XML, and RSS feeds, plus direct programmatic integration with Apify REST APIs.

**Can I schedule daily runs for new job postings?**
Yes. You can use Apify Schedules to trigger the scraper daily or weekly. By filtering with `postedWithinDays: "1"` or checking `firstPublishedAt`, you can maintain a fresh pipeline of newly opened Polish job listings.

**Is an account or login required?**
No account or login is required. The actor reads from public listing feeds.

***

### 🔗 Related scrapers

- [SEEK Scraper — Australia & NZ Job Listings with Salary](https://apify.com/haketa/seek-scraper)
- [ZipRecruiter Job Listings & Salary Scraper](https://apify.com/haketa/ziprecruiter-scraper)
- [Naukri Scraper — India Jobs & Salaries](https://apify.com/haketa/naukri-scraper)
- [Internshala Scraper — India Internships & Fresher Jobs](https://apify.com/haketa/internshala-scraper)
- [Workana Jobs Scraper — Freelance Projects & Budgets](https://apify.com/haketa/workana-scraper)

***

### 📋 Changelog

#### Version 1.2 (2026-11)

- **Unlocked 1,000+ Pagination**: Set `maxPagesPerSearch` default to `0` (unlimited, governed by `maxItems`) for deep pagination.
- **Enhanced Salary Parsing**: Normalized Polish salary text into structured `salaryMin`, `salaryMax`, currency (PLN/EUR), and period.
- **Fast Prefill Performance**: Verified 100-item prefill runs complete in under 20 seconds using massachusetts gateway API.
- **Schema & Documentation Update**: Added detailed field coverage indicators and multi-language API integration examples.

#### Version 1.1 (2026-10)

- Added automatic fallback to nationwide Poland feed when keyword searches yield fewer items than requested.
- Added AI summary HTML tag stripping.

#### Version 1.0 (2026-08)

- Initial release with keyword, city, contract type, work mode, and seniority filtering.

# Changelog

This Actor's version history is a separate document: https://apify.com/haketa/pracuj-scraper/changelog.md

# Actor input Schema

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

Job keywords to search, e.g. 'python', 'accountant', 'kierowca'. Each is searched separately. Leave empty for a nationwide sample.

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

Optional Polish city or area, e.g. 'warszawa', 'kraków', 'wrocław'. Applies to every keyword.

## `contractTypes` (type: `array`):

Filter by contract type. Leave empty for all.

## `workModes` (type: `array`):

Filter by work mode. Leave empty for all.

## `seniorityLevels` (type: `array`):

Filter by seniority. Leave empty for all.

## `salaryOnly` (type: `boolean`):

Return only job offers that publish a salary (Pracuj hides pay on many listings).

## `postedWithinDays` (type: `string`):

Only offers published within the last N days.

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

Optional. Paste Pracuj.pl search URLs (e.g. 'https://www.pracuj.pl/praca/java;kw/warszawa;wp'). When provided, the keyword is read from the URL and the filters above still apply.

## `scrapeDetails` (type: `boolean`):

Visit each offer page for the full description and requirements. This adds one request per offer, so it increases run time — leave off for fast, low-cost scraping, since the search results already include title, company, salary, locations and an AI summary.

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

Maximum job offers to return across all keywords. 0 = unlimited.

## `maxPagesPerSearch` (type: `integer`):

Cap on result pages per keyword (50 offers/page). 0 = unlimited (bounded by Max items).

## `requestDelay` (type: `integer`):

Delay between requests. 300–800 ms keeps the run smooth.

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

Uses datacenter proxies by default (fast and low-cost) and automatically escalates to PL residential if a block is detected. You can also pin your own proxy.

## Actor input object example

```json
{
  "keywords": [
    "python"
  ],
  "location": "",
  "contractTypes": [],
  "workModes": [],
  "seniorityLevels": [],
  "salaryOnly": false,
  "postedWithinDays": "0",
  "startUrls": [],
  "scrapeDetails": false,
  "maxItems": 100,
  "maxPagesPerSearch": 0,
  "requestDelay": 400,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}
```

# Actor output Schema

## `datasetItems` (type: `string`):

All extracted Pracuj.pl job offers for this run.

## `overviewTable` (type: `string`):

A clean, human-readable table of the scraped job offers.

# 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": [
        "python"
    ],
    "location": "",
    "contractTypes": [],
    "workModes": [],
    "seniorityLevels": [],
    "startUrls": [],
    "maxItems": 100,
    "proxyConfiguration": {
        "useApifyProxy": true
    }
};

// Run the Actor and wait for it to finish
const run = await client.actor("haketa/pracuj-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": ["python"],
    "location": "",
    "contractTypes": [],
    "workModes": [],
    "seniorityLevels": [],
    "startUrls": [],
    "maxItems": 100,
    "proxyConfiguration": { "useApifyProxy": True },
}

# Run the Actor and wait for it to finish
run = client.actor("haketa/pracuj-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": [
    "python"
  ],
  "location": "",
  "contractTypes": [],
  "workModes": [],
  "seniorityLevels": [],
  "startUrls": [],
  "maxItems": 100,
  "proxyConfiguration": {
    "useApifyProxy": true
  }
}' |
apify call haketa/pracuj-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,haketa/pracuj-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/szbobLtSjbdbj0nIu/builds/kgjQFmVYRFhJcKEu8/openapi.json
