NoFluffJobs Scraper - IT Jobs, Salaries & Companies
Pricing
from $1.00 / 1,000 results
NoFluffJobs Scraper - IT Jobs, Salaries & Companies
Scrape NoFluffJobs IT jobs across Poland, Czechia, Slovakia, Hungary and the Netherlands. Search with filters or URLs and extract salaries, skills, descriptions, tasks, benefits, hiring steps, company size, GPS and office locations.
Pricing
from $1.00 / 1,000 results
Rating
0.0
(0)
Developer
Abot API
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
NoFluffJobs Scraper: IT Jobs With Disclosed Salary, Skills & Company Data
NoFluffJobs Scraper turns NoFluffJobs, the Central and Eastern European tech job board known for showing salary ranges upfront, into a clean IT jobs data feed. Search five markets (Poland, Czechia, Slovakia, Hungary and the Netherlands) by category, seniority, technology, city, remote-only and salary range, or paste NoFluffJobs URLs. Every job comes back as one deduplicated record with its disclosed pay, required and nice-to-have skills, daily tasks, benefits, recruitment steps, company size and every office location merged into a single array. Export to JSON, CSV or Excel, or pull results straight into your app through the API.
Why This Scraper?
- Salary transparency by default. Every record carries the disclosed pay range, contract type and a full per-contract-type breakdown, with hourly-quoted postings converted onto the same monthly figure as everything else.
- Five markets in one run. Scrape Poland, Czechia, Slovakia, Hungary and the Netherlands, individually or all at once.
- Structured search. Filter by category, seniority, employment type, posting language, city, technology, remote-only and salary range, no need to hand-build search URLs.
- Full detail depth on demand. Required and nice-to-have skills, daily tasks, benefits, equipment, recruitment steps, company size and exact office GPS coordinates.
- Clean, deduplicated output. One record per job, with every office city and its coordinates merged into a single locations array instead of one row per location.
- Built for monitoring. Incremental mode returns only new and changed jobs on a recurring schedule, and a run that could not read the site fails loudly instead of returning an empty dataset.
- Resumable long runs. Continue an interrupted crawl and collect only the delta, or let an unlimited run checkpoint itself so a platform migration never restarts it from page one.
Use Cases
- Recruiters and talent teams: benchmark disclosed salary ranges and required skills across the region before writing a job ad.
- Compensation and HR analysts: build a dataset of published pay ranges by seniority, technology and region.
- Job boards and career sites: mirror open roles from five Central and Eastern European markets into your own listings.
- Job seekers and career tools: track new and updated postings for a technology, city or seniority level on a schedule.
- Market researchers: study remote-work adoption, contract types and benefits across the region's tech sector.
Data You Get
Sample shape: values are illustrative placeholders, not from a live listing.
| Field | Example |
|---|---|
id | senior-java-developer-sample-company-warszawa |
title | Senior Java Developer |
url | https://nofluffjobs.com/pl/job/senior-java-developer-sample-company-warszawa |
region | pl |
companyName / companySize | Sample Tech Company / 500 - 999 |
category / seniority | backend / ["senior"] |
technology | Java |
remote / fullyRemote / remotePercent | true / false / 50 |
cities | ["Remote", "Warszawa"] |
locations | [{ "city": "Warszawa", "country": "Poland", "latitude": 52.0, "longitude": 21.0 }] |
salaryFrom / salaryTo / salaryCurrency | 21840 / 23520 / PLN |
salaryType | b2b |
salaryRanges | [{ "type": "b2b", "from": 130, "to": 140, "currency": "PLN", "period": "Hour" }] |
description | Full job description text appears here when fetchDetails is on. |
requirementsMust / requirementsNice | [{ "name": "Java", "type": "main" }] / [{ "name": "Kafka", "type": "nice" }] |
dailyTasks | ["Design backend services", "Build REST APIs"] |
benefits / officePerks | ["Private healthcare", "Sport card"] / ["Free coffee"] |
equipment | { "computer": "Notebook", "operatingSystem": "Linux" } |
recruitmentSteps | ["Phone screen", "Technical interview"] |
onlineInterviewAvailable | true |
posted / renewed / lastActivity | 2026-01-01T00:00:00.000Z |
expiresAt | 2026-02-01T00:00:00.000Z |
When fetchDetails is off, only the list-level fields are populated (title, company, salary, category, seniority, cities, technology, remote, url); the detail-only fields stay null.
How to Use
- Pick a mode:
search(build a query from the filters) orurl(paste NoFluffJobs links). - For search mode, pick a region and any filters you need. For URL mode, paste search pages or individual job links.
- Set Max jobs to control run size and cost, then click Start.
- Download the dataset as JSON, CSV or Excel, or read it through the API.
Basic search in Poland:
{"mode": "search","region": "pl","maxListings": 100}
Senior backend Java jobs that offer remote work, paying at least 20000 a month:
{"mode": "search","region": "pl","category": "backend","seniority": "senior","technology": "java","remoteOnly": true,"minSalary": 20000,"maxListings": 100}
All five markets at once:
{"mode": "search","region": "all","maxListings": 500}
Paste URLs (two search pages from different markets):
{"mode": "url","urls": ["https://nofluffjobs.com/pl/devops","https://nofluffjobs.com/cz/backend?criteria=seniority%3Dsenior"],"maxListings": 200}
Run it from your code
Python:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("abotapi/nofluffjobs-scraper").call(run_input={"mode": "search", "region": "pl", "maxListings": 50})for job in client.dataset(run["defaultDatasetId"]).iterate_items():print(job["title"], job["companyName"], job["salaryFrom"], job["salaryTo"])
JavaScript:
import { ApifyClient } from 'apify-client';const client = new ApifyClient({ token: '<YOUR_APIFY_TOKEN>' });const run = await client.actor('abotapi/nofluffjobs-scraper').call({ mode: 'search', region: 'pl', maxListings: 50 });const { items } = await client.dataset(run.defaultDatasetId).listItems();
Or connect it to Make, Zapier, n8n, Google Sheets or webhooks from the Integrations tab.
How Max jobs and Max pages interact
Max jobs (maxListings) is the main limit on how many records come back; 0 means unlimited. Max pages (maxPages) is an optional safety bound on how many search-result pages are walked per query or region (about 20 jobs per page); leave it at 0 to walk the whole catalogue. With Max jobs and Max pages both at 0, the run walks every result page for the region(s) you picked, stopping on its own once the region reports no more pages or a page comes back empty. Leading pages made up only of jobs already collected (for example on a resumed run) are skipped through, not treated as the end. One limitation: once a query or URL has returned at least one new job, a later page made up only of jobs the run already collected is treated as the end of that query. If you paste overlapping search URLs in one run (say a broad category page plus a narrower one inside it), the later URL can stop early and miss jobs further down its pages; paste non-overlapping URLs, or run overlapping ones as separate runs.
Salary filter, on both modes
Minimum salary and Maximum salary apply in search mode and in URL mode alike, including a single pasted job link. Both are compared as a monthly gross figure: a posting quoted per hour is converted to its monthly equivalent first, so an hourly job is judged on the same basis as a monthly one. A posting that discloses no salary this actor can read is skipped while a bound is set, and the run log names it separately from a job that simply pays outside your range, so an empty result can always be traced back to why.
Resume and recurring updates
- Resume (
resumeFromRunId) continues one interrupted run: paste its run or dataset id and this run collects only the jobs that run doesn't already have (a delta), so you don't pay twice. Long unlimited runs also checkpoint their own progress, so an Apify platform migration or a Resurrect of a failed run picks up where it left off instead of starting over. - Incremental mode (
incrementalMode) is for recurring runs over the same search. Each job is classifiedNEW,UPDATED(withchangedFields),UNCHANGED(suppressed and not billed unlessemitUnchangedis on),REAPPEARED, orEXPIRED(only after a run that scanned the whole tracked search end to end, and only withemitExpiredon; a capped, resumed or partly blocked run never marks anything expired). If you useemitExpiredin URL mode, keep the pasted search URLs non-overlapping: an overlapping later URL can stop early (see above) and its unreached jobs would be reportedEXPIREDeven though they are still live.stateKeynames or shares the stored baseline; leave it empty and the actor derives one from your filters. With incremental mode off, output is exactly as before.
Send results into your apps (MCP connectors)
Optionally pipe the scraped results into the apps you already use, via Model Context Protocol (MCP) connectors. This is an extra delivery step after the scrape: the Apify dataset is never changed.
What gets written to the connector: a condensed, human-readable summary of each record, not the full JSON. Each item becomes one entry with a title and its key fields flattened to plain text. The complete record always stays in the Apify dataset.
- Authorize a connector once under Apify → Settings → Integrations (Notion, Linear, Airtable, or Apify).
- Select it in the "Pipe results into your apps" input field. (If the picker is empty, you haven't authorized a connector yet.)
- For Notion, also set
notionParentPageUrlto the page where items should be created.
The connection is mediated by Apify's MCP proxy, so this actor never sees your third-party credentials. Leave the field empty to skip.
Input Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
mode | string | search | search builds a query from the filters below; url fetches the URLs you paste. |
region | string | pl | pl, cz, sk, hu, nl, or all. Search mode only. |
keyword | string | (empty) | Free-text search across roles, technologies and companies. Search mode only. |
category | string | (any) | Job category, e.g. backend, frontend, devops, testing, data. Search mode only. |
seniority | string | (any) | trainee, junior, mid, senior, expert. Search mode only. |
employmentType | string | (any) | b2b, permanent, mandate contract, internship. Search mode only. |
jobLanguage | string | (any) | Language the posting is written in. Search mode only. |
city | string | (any) | Restrict to one city. Search mode only. |
technology | string | (any) | Require a specific skill or technology. Search mode only. |
urls | array | sample | NoFluffJobs URLs to fetch. URL mode only. |
remoteOnly | boolean | false | Only jobs that offer remote work. Applies in search mode and to pasted search pages in URL mode; a single pasted job link is not remote-filtered. |
sortBy | string | relevance | Result order: relevance, newest, salary high to low, salary low to high. Applied server-side. Applies in both search mode and URL mode. |
minSalary | integer | (none) | Minimum monthly gross, region currency. Applies in both search mode and URL mode. |
maxSalary | integer | (none) | Maximum monthly gross, region currency. Applies in both search mode and URL mode. |
fetchDetails | boolean | true | Add the full detail fields per job (description, skills, tasks, benefits, equipment, recruitment steps, GPS). |
maxListings | integer | 20 | Main limit: maximum number of jobs to return. 0 means unlimited (then Max pages becomes the cap). |
maxPages | integer | 0 | Safety bound on search-result pages walked per query or region. 0 means unlimited (walk until the storefront reports no more pages). |
resumeFromRunId | string | (none) | Continue one interrupted run: id of a previous run (or dataset) of this actor. Jobs already collected there are skipped. |
incrementalMode | boolean | false | Recurring monitoring of the same search: return only what changed (NEW/UPDATED/REAPPEARED/EXPIRED) each run. |
stateKey | string | (none) | Names an incremental-mode monitoring campaign. Leave empty to auto-derive one from the filters. |
emitUnchanged | boolean | false | Incremental mode only. Also return (and bill) every UNCHANGED job alongside NEW/UPDATED/REAPPEARED. |
emitExpired | boolean | false | Incremental mode only. Also return a tracked job that is no longer found, once, after a complete scan. |
proxy | object | Apify Datacenter | Connection settings. |
residentialRequestCap | integer | 0 | If Residential is selected, switch to Datacenter after this many residential requests. 0 disables the cap. |
residentialBudgetMb | integer | 0 | If Residential is selected, switch to Datacenter after this many MB pulled over residential. 0 disables the cap. |
mcpConnectors | array | (none) | Optional: send a summary of each record to apps you authorized under Integrations. |
notionParentPageUrl | string | (none) | Notion connector only: page under which records are created. |
maxNotifyListings | integer | 50 | Cap on items written to each connector per run. |
Output Example
Sample shape: values are illustrative placeholders, not from a live listing.
{"id": "senior-java-developer-sample-company-warszawa","reference": "REF-0001","title": "Senior Java Developer","url": "https://nofluffjobs.com/pl/job/senior-java-developer-sample-company-warszawa","region": "pl","companyName": "Sample Tech Company","companySize": "500 - 999","companyProfileUrl": "https://nofluffjobs.com/company/sample-tech-company-00000000","category": "backend","seniority": ["senior"],"technology": "Java","remote": true,"fullyRemote": false,"remotePercent": 50,"cities": ["Remote", "Warszawa"],"locations": [{ "city": "Warszawa", "country": "Poland", "countryCode": "POL", "latitude": 52.0, "longitude": 21.0 }],"salaryFrom": 21840,"salaryTo": 23520,"salaryCurrency": "PLN","salaryType": "b2b","salaryRanges": [{ "type": "b2b", "from": 130, "to": 140, "currency": "PLN", "period": "Hour" }],"description": "Full job description text appears here when fetchDetails is on.","dailyTasks": ["Design backend services", "Build REST APIs"],"requirementsMust": [{ "name": "Java", "type": "main" },{ "name": "Spring", "type": "main" }],"requirementsNice": [{ "name": "Kafka", "type": "nice" }],"requirementLanguages": ["en"],"benefits": ["Private healthcare", "Sport card"],"officePerks": ["Free coffee"],"equipment": { "computer": "Notebook", "operatingSystem": "Linux" },"recruitmentSteps": ["Phone screen", "Technical interview"],"recruitmentLanguages": ["pl", "en"],"onlineInterviewAvailable": true,"posted": "2026-01-01T00:00:00.000Z","expiresAt": "2026-02-01T00:00:00.000Z"}
Plan Requirement
This actor runs on the Apify Datacenter connection by default. Residential is offered as an option for users who want geo-diverse exit IPs; it is not required for this site. If you do select a Residential connection, use the residential request cap and traffic budget to keep costs predictable, and the actor automatically switches back to the Datacenter connection once a cap is reached.
FAQ
How much does it cost?
You pay per record returned. The Pricing tab shows the current rates. Use Max jobs to cap the cost of any run.
Is it legal to scrape NoFluffJobs?
This actor collects only publicly available job listing data. You are responsible for how you use it: follow NoFluffJobs's terms and the laws that apply to you, and get legal advice if you plan commercial redistribution.
Can I get only new or changed jobs on a schedule?
Yes. Schedule the actor from the Schedules tab and turn on Incremental mode. Each run then returns only new, updated, reappeared or expired jobs, and unchanged ones are not billed.
What is the difference between Resume and Incremental mode?
Resume continues ONE specific interrupted run by id, and returns the delta against that one run's dataset. Incremental mode is for a search you run again and again on a schedule: the actor remembers its own baseline between runs, no id to paste, and classifies every job against what it saw last time. Use Resume to finish a crawl that stopped; use Incremental mode to monitor the same search over time.
Why did my run fail instead of returning an empty dataset?
If every request to NoFluffJobs was refused, the run stops with a clear message so "no jobs matched" is never confused with "nothing could be read". Retry in a few minutes, or pick a different connection. If a minimum or maximum salary removed everything, the run still succeeds and names the filter as the reason in its final message.
Can I use it with AI agents or MCP?
Yes. Call it from any Apify integration or MCP client, and use the connector field to push results into Notion, Linear or Airtable.
🔗 Want more jobs data?
Pair this actor with these related scrapers from the same team:
| 💼 Jobsite UK From $1/1K. Collect UK job listings from Jobsite.co.uk at scale. Search by keyword... | 🏨 Caterer.com Scraper Scrape UK hospitality jobs from Caterer.com, including chef, hotel, restaurant, bar, and... |
| 💼 Reed.co.uk Scraper Scrape Reed.co.uk jobs, companies, courses, and reviews. Search by keyword, location... | 💼 Cwjobs UK From $1/1k. Scrape tech and IT jobs from CWJobs.co.uk into clean, structured data. Search... |
| 💼 Jobs.cz Scrape Czech job listings from Jobs.cz. Search builder (keyword, location, field, salary... | 💼 Hiring.Cafe Jobs From $1/1K. Unlock powerful Hiring.Cafe job data extraction. Use advanced filters or URLs... |
💬 Support & custom scrapers
- 🐞 Found a bug or a missing field? Open a ticket on the Issues tab. We usually reply within hours.
- 🛠️ Need another site, extra fields or a private build? Email abotapi@proton.me or message Telegram @abotapi.
- ⭐ Enjoying it? A quick review on the actor page helps other users find it.