# Praca.pl Jobs Scraper & Hiring Monitor (`mrarcode/praca-scraper`) Actor

Track new & changed Praca.pl job offers. Incremental monitoring with salary, company & contract data — get only what changed, not the same list every run.

- **URL**: https://apify.com/mrarcode/praca-scraper.md
- **Developed by:** [MrArCode](https://apify.com/mrarcode) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 83.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 job offers

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/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## Praca.pl Jobs Scraper & Monitoring

Extract structured job listings from Praca.pl with salary data, company information, locations, work modes, contract types, full job descriptions, and incremental change tracking.

This Actor is designed for recruiters, HR analytics teams, job market researchers, data teams, lead generation workflows, and AI agents that need clean job data from the Polish labor market.

### What does it do?

This scraper collects job offers from Praca.pl search pages and returns structured records ready for analysis, automation, monitoring, or AI workflows.

It can work in two modes:

- **Fast listing mode** — collects core data directly from search results.
- **Full details mode** — visits each job offer page and enriches the output with full descriptions and direct application URLs.

It also supports **incremental monitoring**, so repeated runs can return only new, updated, reappeared, or expired job offers.

### Key features

- Search Praca.pl by keyword and location
- Explode multi-location grouped offers into individual structured records with stable, unique `jobId` hashes
- Use custom starting URLs via `customUrls` to scrape target searches directly
- Extract salary ranges into structured fields: `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryRanges`
- Extract contract types, work modes, and remote-work flags
- Optional full detail enrichment: extract full description and direct apply URL
- Incremental mode with `NEW`, `UPDATED`, `UNCHANGED`, `REAPPEARED`, and `EXPIRED`
- Repost-aware monitoring with optional repost skipping based on role fingerprints
- Compact output mode for AI agents, MCP workflows, and lightweight automations
- Optional description truncation to reduce payload size
- Data quality fields such as `detailFetchStatus` and `dataQualityWarnings`
- Uses Apify residential proxy for Poland when running on the Apify platform

### Use cases

- Monitor new job postings for specific roles
- Track salary ranges for software developers, managers, specialists, or physical workers
- Build HR analytics dashboards and track competitor hiring activity
- Feed job data into AI agents or MCP workflows
- Export structured job data to spreadsheets, databases, CRMs, ATS systems, or BI tools
- Detect new, changed, reappeared, and expired offers over time

### Input

You can use regular search parameters or provide direct Praca.pl search URLs.

#### Basic search example

```json
{
  "query": "programista python",
  "location": "Warszawa",
  "maxResults": 25,
  "includeDetails": false
}
````

#### Full detail enrichment example

```json
{
  "query": "programista",
  "location": "Kraków",
  "maxResults": 10,
  "includeDetails": true
}
```

#### Custom URLs example

```json
{
  "customUrls": [
    "https://www.praca.pl/s-programista,warszawa.html"
  ],
  "maxResults": 10,
  "includeDetails": false
}
```

#### Incremental monitoring example

```json
{
  "query": "programista",
  "location": "Wrocław",
  "maxResults": 50,
  "incremental": true,
  "includeUnchanged": false
}
```

#### Track expired and reappeared offers

```json
{
  "query": "programista",
  "location": "Warszawa",
  "maxResults": 100,
  "incremental": true,
  "trackExpiration": true,
  "includeUnchanged": false
}
```

#### Compact AI/MCP output

```json
{
  "query": "programista",
  "location": "Warszawa",
  "maxResults": 25,
  "compact": true
}
```

#### Limit long descriptions

```json
{
  "query": "programista",
  "location": "Warszawa",
  "maxResults": 10,
  "includeDetails": true,
  "descriptionMaxLength": 1000
}
```

### Input fields

| Field                  |    Type | Description                                                                                    |
| ---------------------- | ------: | ---------------------------------------------------------------------------------------------- |
| `query`                |  string | Search keyword or position level, for example `programista`, `kierownik`.                      |
| `location`             |  string | City or area, for example `Warszawa`, `Kraków`, `Wrocław`.                                     |
| `customUrls`           |   array | List of direct starting search page URLs on praca.pl to scrape directly.                       |
| `maxResults`           | integer | Maximum number of job records to return. Use `0` for unlimited.                                |
| `includeDetails`       | boolean | Visit each job page and enrich the listing with full details. Slower, but returns richer data. |
| `incremental`          | boolean | Enables change tracking between runs.                                                          |
| `stateKey`             |  string | Optional custom state key for separating monitoring contexts.                                  |
| `includeUnchanged`     | boolean | Include unchanged offers in incremental output. Unchanged records are useful for snapshots.    |
| `trackExpiration`      | boolean | Detect expired and reappeared offers. Requires `incremental=true`.                             |
| `skipReposts`          | boolean | Skip detected reposts. Requires `trackExpiration=true`.                                        |
| `compact`              | boolean | Return only core fields for AI agents and lightweight workflows.                               |
| `descriptionMaxLength` | integer | Truncate job descriptions to a maximum number of characters. Use `0` for no limit.             |
| `bypassCharging`       | boolean | Run in dry-run mode without charging billing (useful for testing or local runs).               |
| `offerChargeLimit`     | integer | Hard budget cap on the number of charged events for this run.                                  |

### Output example

```json
{
  "jobId": "61a5b8cfec0b1c725b757937a4a3a3646f037fa797dc3b70ae377cd0226ecdc8f",
  "offerId": "11160403",
  "title": "Programista Python",
  "company": "Acrebi Sp. z o.o.",
  "companyLogoUrl": "https://www.praca.pl/graphics/logo.png",
  "companyProfileUrl": "https://www.praca.pl/firma/acrebi",
  "location": "Warszawa",
  "locations": [
    {
      "city": "Warszawa"
    }
  ],
  "allOfferUrls": [
    "https://www.praca.pl/oferta/programista-python-warszawa_11160403.html"
  ],
  "locationCount": 1,
  "salaryText": "8 000 - 12 000 zł brutto/mies.",
  "salaryMin": 8000.0,
  "salaryMax": 12000.0,
  "salaryCurrency": "PLN",
  "salaryPeriod": "month",
  "salaryRanges": [
    {
      "min": 8000.0,
      "max": 12000.0,
      "currency": "PLN",
      "period": "month"
    }
  ],
  "contractTypes": ["Umowa o pracę"],
  "workModes": ["praca zdalna"],
  "isRemote": true,
  "technologies": [],
  "postedDate": "2026-06-20T12:00:00Z",
  "url": "https://www.praca.pl/oferta/programista-python-warszawa_11160403.html",
  "portalUrl": "https://www.praca.pl",
  "source": "praca.pl",
  "changeType": "NEW",
  "firstSeenAt": "2026-06-23T12:00:00Z",
  "lastSeenAt": "2026-06-23T12:00:00Z",
  "detailFetchStatus": "skipped",
  "dataQualityWarnings": []
}
```

Fields with default or empty values are omitted here for brevity; real records include all fields listed in 'Output fields overview'.

### Full details output

When `includeDetails=true`, the Actor enriches each offer with additional fields:

- `description` (full job description body HTML)
- `applyUrl` (direct external application widget URL)
- `expirationDate` (timestamp parsed from JSON-LD if available)

Example detail fields:

```json
{
  "description": "<div>Detailed job description body...</div>",
  "applyUrl": "https://www.praca.pl/aplikuj/11160403",
  "expirationDate": "2026-07-20T12:00:00Z",
  "detailFetchStatus": "success"
}
```

### Compact output

Compact mode is designed for AI agents, MCP workflows, automations, and low-payload integrations.

Enable it with:

```json
{
  "compact": true
}
```

Compact output includes only core fields:

```json
{
  "jobId": "61a5b8cfec0b1c725b757937a4a3a3646f037fa797dc3b70ae377cd0226ecdc8f",
  "title": "Programista Python",
  "company": "Acrebi Sp. z o.o.",
  "location": "Warszawa",
  "url": "https://www.praca.pl/oferta/programista-python-warszawa_11160403.html",
  "salaryMin": 8000.0,
  "salaryMax": 12000.0,
  "salaryCurrency": "PLN",
  "salaryPeriod": "month",
  "contractTypes": ["Umowa o pracę"],
  "workModes": ["praca zdalna"],
  "technologies": [],
  "changeType": "NEW"
}
```

### Incremental mode

Incremental mode lets you monitor a search over time.

When `incremental=true`, the Actor stores state between runs and classifies each job offer using `changeType`.

Supported change types:

| changeType   | Meaning                                                                       |
| ------------ | ----------------------------------------------------------------------------- |
| `NEW`        | The offer was not seen in previous runs for this search context.              |
| `UPDATED`    | The offer was seen before, but selected fields changed.                       |
| `UNCHANGED`  | The offer was already seen and did not change.                                |
| `REAPPEARED` | The offer was previously marked as expired and appeared again.                |
| `EXPIRED`    | The offer was previously active but is no longer present in a completed scan. |

#### Example: return only new or changed offers

```json
{
  "query": "programista",
  "location": "Warszawa",
  "incremental": true,
  "includeUnchanged": false,
  "maxResults": 100
}
```

#### Example: include unchanged offers too

```json
{
  "query": "programista",
  "location": "Warszawa",
  "incremental": true,
  "includeUnchanged": true,
  "maxResults": 100
}
```

### State key

By default, the Actor automatically creates a state key from the search parameters.

You can also provide a custom `stateKey`:

```json
{
  "query": "programista",
  "location": "Warszawa",
  "incremental": true,
  "stateKey": "programista-warsaw-monitor"
}
```

Use `stateKey` when you want full control over separate monitoring contexts.

### Expired and reappeared offers

To track expired and reappeared offers, enable:

```json
{
  "incremental": true,
  "trackExpiration": true
}
```

The Actor only detects expired offers after a completed scan. If a scan is interrupted, hits a request error, parser error, budget limit, `maxResults`, or page safety limit, expired detection is skipped to prevent false positives.

This protects users from fake expiration events.

### Repost detection

When `trackExpiration=true`, the Actor can detect likely reposts using a content fingerprint based on role-identifying fields.

Enable repost skipping with:

```json
{
  "incremental": true,
  "trackExpiration": true,
  "skipReposts": true
}
```

This is useful when employers repost very similar jobs under new offer IDs.

### Data quality fields

Each record includes fields that help you understand how complete the data is:

| Field                 | Meaning                                                         |
| --------------------- | --------------------------------------------------------------- |
| `detailFetchStatus`   | `skipped`, `success`, or `failed` (if the fetch failed or empty details were parsed). |
| `dataQualityWarnings` | List of warnings if enrichment failed or partial data was used. |

Example:

```json
{
  "detailFetchStatus": "failed",
  "dataQualityWarnings": [
    "detail page fetch failed after retries; using listing data only"
  ]
}
```

### Performance notes

`includeDetails=false` is faster and uses fewer requests.

`includeDetails=true` performs one additional request per job offer and may take longer, especially for large result sets.

Recommended settings:

- Use `includeDetails=false` for broad market monitoring.
- Use `includeDetails=true` when you need full descriptions and application URLs.
- Use `compact=true` for AI workflows and lightweight automations.
- Use `descriptionMaxLength` to reduce output size when using LLMs.

### Limitations

- The Actor extracts publicly available job offer data from Praca.pl.
- Full detail enrichment depends on the availability and structure of the individual job offer page.
- Some offers may not include salary information.
- Some offers may not include apply URLs.
- `EXPIRED` detection requires a completed incremental scan.
- Repost detection is heuristic and based on content fingerprints.
- `includeDetails=true` is slower than listing-only mode.

### Responsible usage

Use this Actor responsibly and in accordance with applicable laws, platform terms, and data protection rules.

The Actor is intended for collecting publicly available job listing data. You are responsible for how you use, store, process, and share the extracted data.

### Pricing

This is a pay-per-event Actor. You only pay for the job offers successfully scraped, and the per-record price includes all residential proxy and platform usage costs (there is no separate, unexpected proxy bill).

### FAQ

#### Does this Actor support direct Praca.pl search URLs?

Yes. Use the `customUrls` field.

#### Can I monitor only new jobs?

Yes. Use:

```json
{
  "incremental": true,
  "includeUnchanged": false
}
```

#### Can I get full job descriptions?

Yes. Set:

```json
{
  "includeDetails": true
}
```

#### Can I reduce output size for AI agents?

Yes. Use:

```json
{
  "compact": true
}
```

or use:

```json
{
  "descriptionMaxLength": 1000
}
```

#### Are unchanged records charged?

In incremental mode, unchanged records are intended for snapshot completeness and are not treated as chargeable change events.

#### Why did I get zero records in incremental mode?

If `incremental=true` and `includeUnchanged=false`, a zero-record run usually means there were no new or changed offers for that search context.

### Example monitoring workflow

1. Run the Actor once with `incremental=true`.
2. The first run returns offers as `NEW`.
3. Schedule the Actor daily or hourly.
4. Later runs return only changes if `includeUnchanged=false`.
5. Use `trackExpiration=true` to detect offers that disappeared from a completed scan.
6. Use `compact=true` if the output is consumed by an AI agent or automation.

### Output fields overview

Main fields include:

- `jobId`
- `offerId`
- `title`
- `company`
- `companyLogoUrl`
- `companyProfileUrl`
- `location`
- `locations`
- `allOfferUrls`
- `locationCount`
- `salaryText`
- `salaryMin`
- `salaryMax`
- `salaryCurrency`
- `salaryPeriod`
- `salaryRanges`
- `contractTypes`
- `workModes`
- `isRemote`
- `technologies`
- `postedDate`
- `expirationDate`
- `url`
- `portalUrl`
- `source`
- `description`
- `applyUrl`
- `changeType`
- `firstSeenAt`
- `lastSeenAt`
- `isRepost`
- `repostOfId`
- `repostDetectedAt`
- `detailFetchStatus`
- `dataQualityWarnings`

# Actor input Schema

## `query` (type: `string`):

Keywords to search for (e.g. 'programista python', 'kierownik').

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

City or city area (e.g. 'Warszawa', 'Kraków').

## `customUrls` (type: `array`):

Explicit starting search page URLs on praca.pl to scrape directly (overrides query and location).

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

Maximum number of job listings to scrape. Set to 0 for unlimited.

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

Fetch and enrich each job offer with full description and apply URL. (Requires one extra request per offer, slower and more proxy intensive).

## `incremental` (type: `boolean`):

If enabled, returns only new or updated offers compared to previous runs. Saves money and proxy requests.

## `stateKey` (type: `string`):

Identifies the unique search context state. If left empty, a key is auto-generated based on the search parameters.

## `includeUnchanged` (type: `boolean`):

If enabled, unchanged job offers from previous runs are also included in output (but NOT charged).

## `trackExpiration` (type: `boolean`):

If enabled, detects when job offers disappear (EXPIRED) or reappear (REAPPEARED) compared to the previous runs.

## `skipReposts` (type: `boolean`):

If enabled, excludes job offers detected as reposts of previously expired offers from output dataset.

## `compact` (type: `boolean`):

Return core fields only (AI-agent/MCP).

## `descriptionMaxLength` (type: `integer`):

Truncate description to N chars (0 = no limit).

## `bypassCharging` (type: `boolean`):

Run in dry-run mode without charging billing (useful for testing or local runs).

## `offerChargeLimit` (type: `integer`):

Hard budget cap on the number of charged events for this run.

## Actor input object example

```json
{
  "query": "programista",
  "location": "Warszawa",
  "customUrls": [],
  "maxResults": 25,
  "includeDetails": true,
  "incremental": true,
  "includeUnchanged": false,
  "trackExpiration": true,
  "skipReposts": false,
  "compact": false,
  "descriptionMaxLength": 0,
  "bypassCharging": false
}
```

# Actor output Schema

## `jobOffers` (type: `string`):

Structured job offer records extracted from Praca.pl.

# 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 = {
    "query": "programista",
    "location": "Warszawa",
    "customUrls": [],
    "maxResults": 25,
    "includeDetails": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("mrarcode/praca-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 = {
    "query": "programista",
    "location": "Warszawa",
    "customUrls": [],
    "maxResults": 25,
    "includeDetails": True,
}

# Run the Actor and wait for it to finish
run = client.actor("mrarcode/praca-scraper").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "query": "programista",
  "location": "Warszawa",
  "customUrls": [],
  "maxResults": 25,
  "includeDetails": true
}' |
apify call mrarcode/praca-scraper --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=mrarcode/praca-scraper",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "Praca.pl Jobs Scraper & Hiring Monitor",
        "description": "Track new & changed Praca.pl job offers. Incremental monitoring with salary, company & contract data — get only what changed, not the same list every run.",
        "version": "0.0",
        "x-build-id": "VsFqVZfmE85lWgk29"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/mrarcode~praca-scraper/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-mrarcode-praca-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/mrarcode~praca-scraper/runs": {
            "post": {
                "operationId": "runs-sync-mrarcode-praca-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/mrarcode~praca-scraper/run-sync": {
            "post": {
                "operationId": "run-sync-mrarcode-praca-scraper",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "properties": {
                    "query": {
                        "title": "Search Keywords",
                        "type": "string",
                        "description": "Keywords to search for (e.g. 'programista python', 'kierownik')."
                    },
                    "location": {
                        "title": "Location",
                        "type": "string",
                        "description": "City or city area (e.g. 'Warszawa', 'Kraków')."
                    },
                    "customUrls": {
                        "title": "Custom URLs (Direct Scrape)",
                        "type": "array",
                        "description": "Explicit starting search page URLs on praca.pl to scrape directly (overrides query and location).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "maxResults": {
                        "title": "Max Results Limit",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Maximum number of job listings to scrape. Set to 0 for unlimited."
                    },
                    "includeDetails": {
                        "title": "Include Full Details (Enrichment)",
                        "type": "boolean",
                        "description": "Fetch and enrich each job offer with full description and apply URL. (Requires one extra request per offer, slower and more proxy intensive)."
                    },
                    "incremental": {
                        "title": "Incremental Mode",
                        "type": "boolean",
                        "description": "If enabled, returns only new or updated offers compared to previous runs. Saves money and proxy requests.",
                        "default": true
                    },
                    "stateKey": {
                        "title": "State Universe Key",
                        "type": "string",
                        "description": "Identifies the unique search context state. If left empty, a key is auto-generated based on the search parameters."
                    },
                    "includeUnchanged": {
                        "title": "Include Unchanged Offers",
                        "type": "boolean",
                        "description": "If enabled, unchanged job offers from previous runs are also included in output (but NOT charged).",
                        "default": false
                    },
                    "trackExpiration": {
                        "title": "Track Expired / Reappeared",
                        "type": "boolean",
                        "description": "If enabled, detects when job offers disappear (EXPIRED) or reappear (REAPPEARED) compared to the previous runs.",
                        "default": true
                    },
                    "skipReposts": {
                        "title": "Skip Reposts",
                        "type": "boolean",
                        "description": "If enabled, excludes job offers detected as reposts of previously expired offers from output dataset.",
                        "default": false
                    },
                    "compact": {
                        "title": "Compact Mode",
                        "type": "boolean",
                        "description": "Return core fields only (AI-agent/MCP).",
                        "default": false
                    },
                    "descriptionMaxLength": {
                        "title": "Max Description Length",
                        "minimum": 0,
                        "type": "integer",
                        "description": "Truncate description to N chars (0 = no limit).",
                        "default": 0
                    },
                    "bypassCharging": {
                        "title": "Bypass Charging (Dry Run)",
                        "type": "boolean",
                        "description": "Run in dry-run mode without charging billing (useful for testing or local runs).",
                        "default": false
                    },
                    "offerChargeLimit": {
                        "title": "Offer Charge Budget Cap",
                        "minimum": 1,
                        "type": "integer",
                        "description": "Hard budget cap on the number of charged events for this run."
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
