# No Fluff Jobs Scraper | NoFluffJobs IT Jobs & Salary Data (`corvuslab/nofluffjobs-scraper`) Actor

Scrape nofluffjobs.com IT jobs in Poland, Czechia & Slovakia, Hungary and Ukraine. 60 fields: salary ranges per contract type (B2B & permanent), skills, seniority, work mode, remote days, company size. Multi-select filters, salaries in one currency, incremental monitoring + alerts.

- **URL**: https://apify.com/corvuslab/nofluffjobs-scraper.md
- **Developed by:** [Corvuslab](https://apify.com/corvuslab) (community)
- **Stats:** 1 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

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

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 No Fluff Jobs Scraper do?

No Fluff Jobs Scraper pulls IT and tech job offers from **nofluffjobs.com** across all four of its markets — **Poland, Czechia & Slovakia, Hungary and Ukraine** — into clean, structured records with **63 fields** each. Every offer on No Fluff Jobs carries a salary, and this Actor turns it into numbers you can sort and compare, optionally **converted to one currency and one period**. It runs with no code and exports to JSON, CSV, Excel, the API or straight into an AI agent.

Give it search terms (`python`, `data engineer`, `react native`) and filters, or paste No Fluff Jobs URLs, and it returns every matching job: title, company, seniority, skills, salary, work mode and dates, plus the full offer when **Fetch full job details** is on (the default).

> New to Apify? Sign up free and use the included monthly platform credit to try this Actor — no credit card needed.

**Why this scraper**

- ⚡ **Fast & low-cost** — lightweight, no browser, no login, so large runs stay cheap.
- 🎚️ **Narrow it down properly** — ten multi-select filters, four markets and several search terms in one de-duplicated run.
- 🏢 **No half-empty records** — company size, work mode, remote days per week and expiry date come back on every job, so you can filter and chart on them without gaps.
- ♻️ **Built for monitoring** — scheduled runs return only what changed, and unchanged jobs are free.

***

### What data can you extract from No Fluff Jobs?

Every record carries **63 fields**. Fields in **bold** are filled on every offer, not only when the employer happens to provide them.

| Group | What you get |
|---|---|
| **Job & role** | Title, URL, market, category, seniority, main technology, skills, must-have and nice-to-have skills, **language requirements**, daily tasks |
| **Salary** | **Min, currency, period, contract type and readable salary text**, max (empty only on open-ended "from X" offers), and a separate range for each contract type the offer lists, with its paid-holiday flag |
| **Work mode & location** | Location, cities, countries, **work mode (remote / hybrid / office)**, **remote days per week**, flexible-remote flag, hybrid arrangement text |
| **Company & hiring** | Company, **company size**, website, logo, company video, contract start, **how to apply**, the employer's own job reference, plus recruitment steps and team methodology when the employer describes them |
| **Dates & status** | **Posted, renewed and expiry dates**, featured flag, online-interview flag, Help-for-Ukraine flag |
| **Description** | **Full offer text** as plain text, HTML and/or Markdown, with an optional length cap |

***

### Key features

- 🔎 **Search or URL scraping** — several search terms per run, or paste No Fluff Jobs search URLs (their filters are kept) and job URLs.
- 🌍 **All four markets at once** — any mix of Poland, Czechia & Slovakia, Hungary and Ukraine, merged and de-duplicated across markets and terms. A job posted in several cities is returned once.
- 🎚️ **Real multi-select filters** — 36 job categories, 7 seniority levels, 5 contract types, cities, remote, required skills, companies, posting language, minimum salary and posting age.
- 💱 **Salary normalization** — report every salary in PLN, EUR, USD, GBP, CHF, CZK, HUF or UAH, per hour, day, month or year, so offers from four markets compare side by side.
- 🧮 **Pay per contract type** — when an offer pays differently on B2B and on a permanent contract, `salaryByContract` keeps both ranges instead of flattening them into one number.
- ♻️ **Monitoring & alerts** — scheduled runs deliver only new, updated and reappeared jobs, and push them to Telegram, Slack, Discord or any webhook (details below).
- 🤖 **AI-ready** — compact and drop-empty output modes keep payloads small for LLMs and MCP.

***

### 🚀 How to scrape No Fluff Jobs

1. Open the Actor and enter one or more **search terms** (e.g. `python`), pick your **markets** and any **filters** — or paste a No Fluff Jobs URL.
2. Set **Max results** and choose whether to **fetch full job details** (on by default).
3. Optionally pick a **salary currency** and **period** so every offer is reported the same way.
4. (Optional) Turn on **incremental mode** and an **alert** channel, then **Schedule** it.
5. Click **Start** — results stream into the Output tab.

Leave everything empty and it returns the 25 most recently posted or refreshed jobs in Poland.

#### Quick-start example input

```json
{
  "searchTerms": ["python"],
  "markets": ["pl", "cz"],
  "seniority": ["senior", "expert"],
  "employmentTypes": ["b2b"],
  "remoteOnly": true,
  "salaryCurrency": "EUR",
  "salaryPeriod": "month",
  "maxResults": 100
}
```

This finds up to 100 senior and expert Python jobs offering a B2B contract that can be done fully remote, across Poland and Czechia & Slovakia, with every salary converted to euros per month — a ready-made shortlist of the best-paid remote B2B roles in the region.

***

### Input

Configure it in the visual editor — no code needed — or pass JSON via the API.
**37 inputs** are available, grouped exactly as in the editor. The **incremental monitoring** and
**notification** inputs are described in their own sections below.

#### 🔎 Search

| Field | Type | What it does |
|---|---|---|
| `searchTerms` | array | Job titles, technologies or keywords, e.g. `python`, `data engineer`. Each term runs as its own search; results are merged and de-duplicated. Empty = every open job. |
| `markets` | array | `pl` (Poland), `cz` (Czechia & Slovakia — one shared market), `hu` (Hungary), `ua` (Ukraine). Defaults to Poland. |
| `startUrls` | array | No Fluff Jobs search URLs (filters in the URL are kept) or job offer URLs. Replaces the search form. |
| `maxResults` | integer | Maximum jobs across all searches (default 25, 0 = every matching job). |

#### 🎚️ Filters

Several values inside one filter widen the search (OR); different filters narrow it (AND).

| Field | Type | What it does |
|---|---|---|
| `categories` | array | 36 categories: backend, frontend, fullstack, mobile, embedded, data, AI / machine learning, DevOps, testing, security, architecture, system administration, IT support, business analysis, BI, project and product management, agile, ERP, UX / UI, game dev, marketing, sales, finance, HR, consulting and more. |
| `seniority` | array | `trainee`, `junior`, `mid`, `senior`, `expert`, `lead`, `head`. |
| `employmentTypes` | array | `b2b`, `permanent`, `zlecenie` (mandate), `uod` (specific-task), `intern`. |
| `cities` | array | e.g. `Warszawa`, `Kraków`, `Praha`, `Budapest` — Polish characters optional. |
| `remoteOnly` | boolean | Fully remote jobs. With cities: jobs in those cities **or** remote. |
| `skills` | array | Only jobs listing one of these technologies, e.g. `Java`, `Kubernetes`, `SQL`. |
| `companies` | array | Only jobs from these employers (name or part of it). |
| `jobLanguages` | array | Posting language: `en`, `pl`, `de`, `hu`, `uk`. |
| `minSalary` | integer | Only jobs paying at least this much, in the salary currency and period chosen below. |
| `postedWithinDays` | integer | Only jobs posted or refreshed in the last N days. |

#### 📄 Output

| Field | Type | What it does |
|---|---|---|
| `salaryCurrency` | enum | `original` or one of PLN, EUR, USD, GBP, CHF, CZK, HUF, UAH. |
| `salaryPeriod` | enum | `original`, `hour`, `day`, `month` or `year`. |
| `includeDetails` | boolean | Fetch the full offer (default on) — see **Data fields** below for what it adds. |
| `descriptionFormat` | enum | `all`, `text`, `html` or `markdown`. |
| `descriptionMaxLength` | integer | Cut descriptions to N characters (0 = full length). |
| `compact` | boolean | Core fields only. |
| `excludeEmptyFields` | boolean | Drop null/empty fields. |

#### ⚙️ Advanced

| Field | Type | What it does |
|---|---|---|
| `proxyConfiguration` | object | Optional and off by default — the Actor works without it. |
| `ignoreUrlFailures` | boolean | Skip start URLs that can't be interpreted instead of failing the run. |
| `maxRequestRetries` | integer | Retries per failed request (0–10, default 3). |

#### More example inputs

A data-engineering salary survey across every market, salaries per year in euros:

```json
{
  "categories": ["data", "artificialIntelligence"],
  "markets": ["pl", "cz", "hu", "ua"],
  "salaryCurrency": "EUR",
  "salaryPeriod": "year",
  "maxResults": 0
}
```

A daily watch on new Kraków and Warsaw Java jobs above a pay floor, pushed to Telegram:

```json
{
  "skills": ["Java"],
  "cities": ["Kraków", "Warszawa"],
  "minSalary": 20000,
  "postedWithinDays": 2,
  "incrementalMode": true,
  "skipReposts": true,
  "telegramToken": "<bot token>",
  "telegramChatId": "@yourchannel"
}
```

Paste a search you built on the site, keep its filters:

```json
{ "startUrls": [{ "url": "https://nofluffjobs.com/pl/backend" }], "maxResults": 200 }
```

***

### Output

Each dataset item is one job offer. A real record with full details on (long text and lists trimmed):

```json
{
  "id": "BIGSKIRV",
  "title": "Senior PHP Software Engineer (Pimcore)",
  "company": "Branchspace sp. z o.o.",
  "url": "https://nofluffjobs.com/pl/job/senior-php-software-engineer-pimcore-branchspace-krakow",
  "market": "pl",
  "category": "backend",
  "seniority": ["Senior"],
  "technology": "PHP",
  "skills": ["PHP", "Symfony", "CMS"],
  "location": "Kraków",
  "cities": ["Kraków"],
  "countries": ["PL"],
  "isFullyRemote": false,
  "workMode": "hybrid",
  "remoteDaysPerWeek": 3,
  "salaryMin": 18000,
  "salaryMax": 25000,
  "salaryCurrency": "PLN",
  "salaryPeriod": "month",
  "salaryContractType": "b2b",
  "salaryText": "18 000–25 000 PLN / month (B2B)",
  "salaryByContract": [
    { "contractType": "b2b", "min": 18000, "max": 25000, "currency": "PLN", "period": "month", "paidHoliday": false }
  ],
  "employmentTypes": ["b2b"],
  "postedAt": "2026-10-08T06:35:46.319000+00:00",
  "expiresAt": "2026-11-07T23:59:59",
  "onlineInterview": true,
  "mustHaveSkills": ["PHP", "Symfony", "CMS", "HTML", "CSS", "JavaScript"],
  "niceToHaveSkills": ["Web security", "DevOps", "AWS", "Pimcore"],
  "languageRequirements": ["en B2 (required)", "pl (nice to have)"],
  "benefits": ["Sport subscription", "Private healthcare", "Small teams", "International projects"],
  "recruitmentSteps": [
    "Screening interview (30 min. Teams meeting)",
    "Product Owner interview (30 min. Teams meeting)",
    "Technical Interview  (1h Teams meeting)",
    "Final interview  (45 min. in person meeting at our office)"
  ],
  "methodology": ["Agile management: Scrum", "Issue tracking tool: Jira", "Version control system: GIT"],
  "contractStart": "ASAP",
  "companySize": "50 - 249",
  "companyWebsite": "https://branchspace.com/",
  "applyMethod": "email",
  "source": "nofluffjobs.com",
  "scrapedAt": "2026-10-08T08:27:57.067004+00:00",
  "detailFetched": true
}
```

#### Data fields

- **Core** (every run) — `id`, `title`, `company`, `url`, `market`, `category`, `seniority`, `technology`, `skills`, `location`, `cities`, `countries`, `isFullyRemote`, `workMode`, `postedAt`, `renewedAt`, `isFeatured`, `onlineInterview`, `help4Ua`, `companyLogo`, `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryContractType`, `salaryText`.
- **Full details** (with `includeDetails`) — `description`, `descriptionHtml`, `descriptionMarkdown`, `requirementsText` (the requirements section in Markdown), `mustHaveSkills`, `niceToHaveSkills`, `languageRequirements`, `dailyTasks`, `benefits`, `officePerks`, `salaryByContract`, `employmentTypes`, `remoteDaysPerWeek`, `remoteFlexible`, `hybridDescription`, `expiresAt`, `companySize`, `companyWebsite`, `companyVideo`, `recruitmentSteps`, `methodology`, `contractStart`, `applyMethod`, `employerReference` (the employer's own job ID, handy for matching against an ATS).
- **Run & monitoring** — `source`, `searchKeyword`, `scrapedAt`, `detailFetched`, `contentHash`, and in incremental mode `changeType` (NEW / UPDATED / UNCHANGED / REAPPEARED / EXPIRED), `firstSeenAt`, `lastSeenAt`, `previousSeenAt`, `expiredAt`, `isRepost`, `repostOfId`, `repostDetectedAt`.

**Output modes.** By default every field the run collects is present, with `null` where the offer has no value. **Compact mode**
returns the core fields only, and **`excludeEmptyFields`** drops empties entirely — together they keep
payloads small for spreadsheets, LLM context windows and MCP tools. EXPIRED records carry only the
job's ID, title, link and tracking dates.

The Output tab also ships a ready-made **Overview** table view: title, company, location, work mode,
seniority, salary, skills, posted date and link.

***

### ♻️ How to monitor No Fluff Jobs with incremental mode

Schedule the Actor and turn on **incremental mode**: each run compares against the last and tags
every job with a `changeType`.

- **NEW**, **UPDATED** and **REAPPEARED** (closed, then back under the same link) are delivered.
- **UNCHANGED** jobs are recognised *before* their details are fetched, so they cost nothing — unless you ask for them.
- A job taken down and **re-posted under a new link** (same title, company and location) is delivered as NEW with `isRepost: true` and the original's ID in `repostOfId` — or left out, and not charged, with **Skip re-posted jobs**. Closed jobs are remembered for 90 days for this.
- **EXPIRED** jobs (closed since the last run) are reported once, on request.

| Field | Type | What it does |
|---|---|---|
| `incrementalMode` | boolean | Compare every run with the last one and tag each job with a `changeType`. |
| `stateKey` | string | Stable name for the tracked search (auto-derived from your settings if blank). |
| `emitUnchanged` | boolean | Also deliver UNCHANGED jobs, for a complete dataset on every run. |
| `emitExpired` | boolean | Also deliver jobs that closed since the last run. |
| `skipReposts` | boolean | Leave out jobs re-posted under a new link. |

| | First run (baseline) | Next run (nothing changed) |
|---|---|---|
| Jobs found | all | all |
| Job details fetched | all | **none** |
| Records emitted & billed | all | **none** |

#### Setting up scheduled monitoring

1. Configure your search terms, markets and filters.
2. Turn on **Incremental mode**.
3. Run it once — this seeds the baseline.
4. Open the **Schedules** tab and set a recurring run (e.g. hourly or daily).
5. Add an alert channel (below).

To catch **closed** jobs, let the run read the whole search (Max results 0, or above the number of
matches) — a capped run never marks jobs as expired, so a limit can't produce false closures. A job
that is still open but has aged out of your **posted within** window is not treated as closed either.

***

### 🔔 How to set up No Fluff Jobs alerts

Get pinged the moment a matching job appears. Fill in only the channels you want — credentials are
secret inputs, encrypted at rest, masked in the UI and never written to the run log.

| Channel | What to configure |
|---|---|
| ✈️ **Telegram** | `telegramToken` (from @BotFather) + `telegramChatId` (chat or channel ID) |
| 💬 **Slack** | `slackWebhookUrl` (Incoming Webhook URL) |
| 🎮 **Discord** | `discordWebhookUrl` (channel webhook URL) |
| 🪝 **Webhook** | `webhookUrl` (+ optional `webhookHeaders`) receives every matched job as JSON, up to 1,000 per run — ideal for n8n / Make / Zapier |

Chat messages list up to `notificationLimit` jobs (1–20, default 5) with title, company, salary, link
and change type, under a header with the full count. In incremental mode, **Alert only on changes**
(`notifyOnlyChanges`) keeps alerts to new, updated and reappeared jobs — so you can keep your dataset
complete with **Include unchanged jobs** while the messages stay short. Every channel fires
independently: a broken channel can't stop the scrape or the others.

***

### 💡 What can you do with No Fluff Jobs data?

#### Benchmark IT salaries across Central Europe

Convert every offer to one currency and period, then compare what a senior DevOps engineer earns in Warsaw, Prague and Budapest. Where an offer pays differently on B2B and on a permanent contract, both ranges come through, so you can see the contract premium too.

#### Build a job alert for your exact profile

Combine seniority, skills, cities, remote and a salary floor, schedule it daily and get only new matches in Telegram or Slack. No more refreshing the site.

#### Recruitment and talent-market intelligence

See which companies are hiring for which stacks, at what seniority and with what hybrid policy, and segment the market by company size and remote days per week.

#### Tech-stack and skills demand research

Track must-have versus nice-to-have skills over time to see which frameworks are rising. Category and seniority counts per market make clean trend charts.

#### Market & competitive research for employers

Check how your offer stacks up against similar roles on pay, remote days, benefits and office perks — against peers of your own size, not giants.

#### Feed AI agents and LLM pipelines

Send job records straight into an LLM context, an MCP tool or a vector store for job matching or career assistants.

***

### 💰 How much does it cost to scrape No Fluff Jobs?

This Actor uses Apify's **pay-per-event** model: a small fee when a run starts, plus a fee for
each job saved to your dataset. See the Actor's **Pricing** tab for the current numbers — they're
rendered live, so this page never goes stale.

It is a lightweight scraper with no browser, which is why its fees can sit at the low end of the
market. Three things cut your bill further:

- **Filters** — jobs you filtered out are never saved and never billed.
- **Details off** — turn off **Fetch full job details** for the fastest, leanest runs when the listing fields are enough.
- **Incremental mode** — after the baseline you pay only for what changed, so your cost scales with how much No Fluff Jobs changes, not with how much you watch:

| Daily churn | of 1,000 tracked | billable records | you save |
|---|---|---|---|
| 5 % | 1,000 | 50 | **95 %** |
| 15 % | 1,000 | 150 | **85 %** |
| 30 % | 1,000 | 300 | **70 %** |

***

### 🔌 Integrations, export & API

Export to **JSON, CSV, Excel** or an HTML table, run on a **schedule**, and connect to **Google
Sheets, Slack, Make, Zapier and n8n**. It also works as an **MCP tool** for AI agents.

To run it from your own code, use the **REST API** or the **JavaScript / Python** clients. Example
with the Apify Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")

run_input = {
    "searchTerms": ["data engineer"],
    "markets": ["pl", "cz", "hu"],
    "salaryCurrency": "EUR",
    "salaryPeriod": "month",
    "maxResults": 50,
}

run = client.actor("corvuslab/nofluffjobs-scraper").call(run_input=run_input)

for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["title"], item["company"], item["salaryMin"], item["salaryMax"], item["salaryCurrency"])
```

***

### ❓ FAQ

**Do I need a No Fluff Jobs account or login?** No — it collects only public job offers and runs out of the box, with no cookies or setup.

**Why do I see Polish jobs in the Czechia & Slovakia market?** That's how No Fluff Jobs works: Czechia and Slovakia are one shared market, and many employers advertise the same role — often remote — in several markets, so the Czech & Slovak pool includes plenty of Poland-based offers. Use `cities` or `countries` in the output to narrow it down. A job advertised in several markets you picked is returned once.

**Does every job have a salary?** Yes. No Fluff Jobs requires a salary on every offer, so `salaryMin`, currency and period are always filled; `salaryMax` is empty only on open-ended "from X" offers. Most offers list one contract type — when one lists several, `salaryByContract` gives each its own range.

**How does the minimum salary filter work?** It follows the site's own rule: a job matches when the top of its range reaches your floor, in the currency and period you chose under **Salary currency** / **Salary period** (Polish złoty per month when those are left as posted).

**Why are `recruitmentSteps`, `methodology` or `hybridDescription` empty on most jobs?** They come from optional sections most employers skip: recruitment steps and methodology appear on roughly one offer in ten, a written hybrid arrangement on fewer. When the employer wrote them, you get them. They also need **Fetch full job details** on.

**Can I get recruiter emails or phone numbers, or a direct apply link?** No. No Fluff Jobs doesn't publish recruiter contact details, and applications go through the site itself, so there is nothing public to extract. You get the job URL, `applyMethod`, the company website and company size instead.

**How many jobs can I get?** Every open job matching your search — set `maxResults` to 0 for no limit.

***

### ⚖️ Is it legal to scrape No Fluff Jobs?

This Actor collects only **publicly available** job offers — the same information anyone can see
on nofluffjobs.com without logging in. You're responsible for how you use it — in particular any
personal information — and for complying with the site's terms and applicable law (including the
GDPR where it applies). Not affiliated with, endorsed by or sponsored by No Fluff Jobs.

***

**Keywords:** No Fluff Jobs scraper · nofluffjobs scraper · nofluffjobs api · nofluffjobs.com scraper · IT jobs Poland · tech jobs Poland · IT jobs Czech Republic · tech jobs Hungary · IT salary data Poland · B2B salary ranges · remote IT jobs Europe · developer job listings · tech salary benchmark · job monitoring · recruitment data · export to CSV · export to Excel · MCP tool for AI agents

# Changelog

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

# Actor input Schema

## `searchTerms` (type: `array`):

Job titles, technologies or keywords, e.g. "python", "data engineer", "react native". A technology name is matched against the job's required skills.

## `markets` (type: `array`):

Which No Fluff Jobs markets to search. Czechia and Slovakia share one market. Defaults to Poland.

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

Optional. Paste No Fluff Jobs search URLs (filters in the URL are kept) or job offer URLs. When set, these replace the search form above.

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

Maximum number of jobs to return across all searches. Set 0 for no limit (every matching job).

## `categories` (type: `array`):

Only jobs in these categories.

## `seniority` (type: `array`):

Only jobs at these levels.

## `employmentTypes` (type: `array`):

Only jobs offering at least one of these contract types.

## `cities` (type: `array`):

Only jobs in these cities, e.g. "Warszawa", "Kraków", "Praha", "Budapest". Polish characters are optional.

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

Include fully remote jobs. On its own it returns remote jobs only; together with cities it returns jobs in those cities OR remote.

## `skills` (type: `array`):

Only jobs that list one of these technologies, e.g. "Java", "Kubernetes", "SQL".

## `companies` (type: `array`):

Only jobs from these employers (name or part of it), e.g. "Allegro".

## `jobLanguages` (type: `array`):

Only jobs whose offer is written in these languages.

## `minSalary` (type: `integer`):

Only jobs paying at least this much, in the salary currency and period chosen below (Polish złoty per month when those are left as posted).

## `postedWithinDays` (type: `integer`):

Only jobs posted or refreshed in the last N days. Leave empty for all.

## `salaryCurrency` (type: `string`):

Report every salary in one currency so jobs compare side by side, or keep each as posted.

## `salaryPeriod` (type: `string`):

Report every salary per hour, day, month or year, or keep each as posted.

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

Add the full description, must-have and nice-to-have skills, daily tasks, benefits, salary for every contract type, hybrid/remote days and company size. Turn off for the fastest runs.

## `descriptionFormat` (type: `string`):

Which representation(s) of the job description to include.

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

Cut descriptions to this many characters. 0 = full length.

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

Emit only the core fields (title, company, location, salary, skills, link). Ideal for AI agents and MCP clients.

## `excludeEmptyFields` (type: `boolean`):

Remove null, empty-string and empty-list fields from each record.

## `incrementalMode` (type: `boolean`):

Track jobs between runs and tag every record NEW / UPDATED / UNCHANGED / EXPIRED. Unchanged jobs are skipped and not charged.

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

Stable name for the tracked search. Leave empty to derive one automatically from your search settings.

## `emitUnchanged` (type: `boolean`):

Also emit jobs that have not changed since the previous run.

## `emitExpired` (type: `boolean`):

Emit jobs that were open last run but are gone now. Needs a run that reads the whole search (Max results 0 or above the number of matches).

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

Leave out jobs that an employer took down and posted again under a new link (same title, company and location as a job already tracked). They are not charged. Every new job still carries isRepost either way.

## `telegramToken` (type: `string`):

Bot token from @BotFather.

## `telegramChatId` (type: `string`):

Chat or channel ID, e.g. "-100123456789" or "@yourchannel".

## `slackWebhookUrl` (type: `string`):

Slack incoming-webhook URL.

## `discordWebhookUrl` (type: `string`):

Discord incoming-webhook URL.

## `webhookUrl` (type: `string`):

Any HTTPS endpoint. Receives a JSON POST with every matched job (up to 1,000 per run) — works with n8n, Make and Zapier.

## `webhookHeaders` (type: `object`):

Extra headers for the webhook request, e.g. {"Authorization": "Bearer xyz"}. Stored encrypted, like the other credentials.

## `notificationLimit` (type: `integer`):

How many jobs to list in each Telegram, Slack or Discord message. The webhook always gets every matched job.

## `notifyOnlyChanges` (type: `boolean`):

In incremental mode, alerts list only new, updated and reappeared jobs, even when Include unchanged jobs is on.

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

Optional. Not needed — the actor works without a proxy. Enable it only if your runs get refused.

## `ignoreUrlFailures` (type: `boolean`):

Skip start URLs that cannot be interpreted instead of failing the whole run.

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

How many times to retry a failed request before giving up on it.

## Actor input object example

```json
{
  "searchTerms": [
    "python"
  ],
  "markets": [
    "pl"
  ],
  "maxResults": 25,
  "remoteOnly": false,
  "salaryCurrency": "original",
  "salaryPeriod": "original",
  "includeDetails": true,
  "descriptionFormat": "all",
  "descriptionMaxLength": 0,
  "compact": false,
  "excludeEmptyFields": false,
  "incrementalMode": false,
  "emitUnchanged": false,
  "emitExpired": false,
  "skipReposts": false,
  "notificationLimit": 5,
  "notifyOnlyChanges": false,
  "proxyConfiguration": {
    "useApifyProxy": false
  },
  "ignoreUrlFailures": true,
  "maxRequestRetries": 3
}
```

# Actor output Schema

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

No description

## `allItems` (type: `string`):

No description

# 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 = {
    "searchTerms": [
        "python"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("corvuslab/nofluffjobs-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 = { "searchTerms": ["python"] }

# Run the Actor and wait for it to finish
run = client.actor("corvuslab/nofluffjobs-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 '{
  "searchTerms": [
    "python"
  ]
}' |
apify call corvuslab/nofluffjobs-scraper --silent --output-dataset

```

## MCP server setup

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