# NoFluffJobs Scraper (Cheap) (`data_api/nofluffjobs-scraper-cheap`) Actor

NoFluffJobs Extractor that scrapes tech job postings and salary ranges from NoFluffJobs, so recruiters and market researchers can track hiring trends and benchmark salaries instantly.

- **URL**: https://apify.com/data\_api/nofluffjobs-scraper-cheap.md
- **Developed by:** [Data API](https://apify.com/data_api) (community)
- **Categories:** Jobs, Automation, Developer tools
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.99 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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/docs.md):

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

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python/docs.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/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

## NoFluffJobs Scraper

![NoFluffJobs Scraper](cover.jpg)

NoFluffJobs is one of the few job boards in Europe where every advert has to show a salary. That makes it a rare source of clean pay data, but the site renders everything in the browser, so copying figures by hand across hundreds of adverts gets old fast. This scraper does the reading for you. Hand it a list of tech terms and it pulls each advert's role title, employer, salary band, required skills, and office location into one tidy row that loads straight into a spreadsheet or database.

### What you get

One row per advert, with the same columns every time. Anything the advert leaves out comes back as `null` rather than disappearing, so your table stays rectangular when you load it. Each row covers three things:

- **The role** — `roleTitle`, `employerName`, `jobField`, `seniorityLevels`, `techStack`, `skillsRequired`, `listingUrl`
- **Pay** — `payMin`, `payMax`, `payCurrency`, `contractType`, `payVisibility`
- **Where and when** — `remoteFriendly`, `officeLocations`, `hybridDetails`, `publishedAt`, `refreshedAt`, `collectedAt`

### Quick start

1. Press **Try for free** and open the input form.
2. Type one or more tech terms into **Tech terms or categories** — `java`, `react`, `devops`, whatever you track.
3. Optionally add a **Location filter** and set **Adverts per term** to cap each search.
4. Hit **Start**, then download the dataset as JSON, CSV, Excel, or XML once the run finishes.

![How it works](how-it-works.jpg)

### Use cases

- **Salary benchmarking** — compare real pay bands across languages, stacks, and seniority before you make an offer
- **Recruitment research** — see which skills and tools European engineering teams ask for right now
- **Hiring trend tracking** — watch which companies are growing their teams and in which cities
- **Remote-work analysis** — measure how much of the market is fully remote versus hybrid
- **Talent sourcing** — build a shortlist of employers hiring for a specific stack and location
- **Market reports** — feed structured pay and demand data straight into your analytics

### Input

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `searchTerms` | array of strings | Yes | Technologies, disciplines, or search handles to crawl, one per line (e.g. java, react, data, devops). |
| `locationFilters` | array of strings | No | Keep only adverts in given cities, countries, or a remote keyword (e.g. Gdańsk, Wrocław, Remote). Accents and case are ignored. |
| `resultsPerTerm` | integer | No | Most adverts to keep per term. Default `15`. |
| `timeoutSeconds` | integer | No | Seconds to wait on a single request before giving up. Default `45`. |

#### Example input

```json
{
    "searchTerms": ["java", "react", "data"],
    "locationFilters": ["Gdańsk", "Wrocław", "Remote"],
    "resultsPerTerm": 15,
    "timeoutSeconds": 45
}
````

### Output

Each advert becomes one row. Every field is always present — values the advert does not disclose come back as `null`, so the dataset loads cleanly into any tool.

#### Example output

```json
{
    "jobId": "senior-java-developer-allegro-warszawa",
    "roleTitle": "Senior Java Developer",
    "employerName": "Allegro",
    "jobField": "backend",
    "seniorityLevels": ["Mid", "Senior"],
    "techStack": "Java",
    "listingUrl": "https://nofluffjobs.com/job/senior-java-developer-allegro-warszawa",
    "remoteFriendly": false,
    "officeLocations": [
        {
            "city": "Warszawa",
            "street": "Targowa 73",
            "postalCode": "03-729",
            "countryName": "Poland",
            "countryCode": "POL"
        }
    ],
    "hybridDetails": "8 days per month in office in Warszawa",
    "payMin": 22000,
    "payMax": 28000,
    "contractType": "b2b",
    "payCurrency": "PLN",
    "payVisibility": "VISIBLE",
    "publishedAt": "2026-06-02T09:00:00.000000+00:00",
    "refreshedAt": "2026-06-09T11:15:00.000000+00:00",
    "skillsRequired": ["Java", "Spring", "Kafka", "SQL"],
    "collectedAt": "2026-06-10T08:30:00.000000+00:00"
}
```

#### Output fields

| Field | Type | Description |
|-------|------|-------------|
| `jobId` | string | Stable identifier for the advert |
| `roleTitle` | string | Headline of the advertised role |
| `employerName` | string | Company that posted the opening |
| `jobField` | string | Discipline the role sits in, such as backend or frontend |
| `seniorityLevels` | array | Experience bands being hired for, e.g. Junior, Mid, Senior, Lead |
| `techStack` | string | Main language or framework attached to the advert |
| `listingUrl` | string | Absolute link to the advert page |
| `remoteFriendly` | boolean | True when the role is fully remote |
| `officeLocations` | array | Workplaces tied to the role (city, street, postal code, country) |
| `hybridDetails` | string | Notes on the hybrid setup, such as required office days |
| `payMin` | integer | Lower bound of the salary band when shared; `null` otherwise |
| `payMax` | integer | Upper bound of the salary band when shared; `null` otherwise |
| `contractType` | string | Engagement form behind the figures, e.g. b2b or uop |
| `payCurrency` | string | Currency the pay band is quoted in, e.g. PLN, EUR, USD |
| `payVisibility` | string | Whether the pay band is shown or held back |
| `publishedAt` | string | ISO 8601 time the advert first went live |
| `refreshedAt` | string | ISO 8601 time the advert was last bumped |
| `skillsRequired` | array | Skills and must-haves pulled from the advert |
| `queryField` | string | Search term being crawled when a row failed |
| `errorMessage` | string | Reason a term could not be collected; absent on healthy rows |
| `collectedAt` | string | ISO 8601 stamp marking when the row was captured |

### Tips for best results

- **Start with a couple of terms.** Run two or three before you queue a long list, so you can confirm the columns match your pipeline.
- **Use `resultsPerTerm` to control spend.** Keep it low while testing, then raise it for the full pull.
- **Lean on the location filter.** It ignores accents and case, so `gdansk` still catches `Gdańsk` and `remote` matches fully remote roles.
- **Expect some blank pay fields.** A handful of employers hide their band; those rows return `null` for `payMin` and `payMax`, with `payVisibility` flagging the gap.
- **Raise `timeoutSeconds`** if you see frequent timeout errors on a slow connection.

### How can I use NoFluffJobs job data?

**How can I use the NoFluffJobs Scraper to benchmark tech salaries?**
Crawl the terms you care about — say `java`, `react`, and `data` — and the scraper returns each advert's `payMin`, `payMax`, `payCurrency`, and `contractType` alongside the role and seniority. Group the rows by stack or experience band to see what the market actually pays before you set an offer.

**How can I track which skills employers want on NoFluffJobs?**
Every row carries `skillsRequired`, `techStack`, and `jobField`. Pull a few weeks of adverts for your discipline, count how often each skill shows up, and you have a live picture of demand to guide hiring, training, or your own learning roadmap.

**How can I export NoFluffJobs adverts for market research?**
Set `resultsPerTerm` high, add the terms and locations you want, and run it. The dataset downloads as JSON, CSV, or Excel, or streams into Google Sheets and other tools through Apify integrations — so a recurring labour-market report becomes a scheduled job instead of manual copy-paste.

### Is it legal to scrape data?

Our actors are ethical and do not extract any private user data, such as email addresses or private contact information. They only extract what the user has chosen to share publicly. We therefore believe that our actors, when used for ethical purposes by Apify users, are safe.

However, you should be aware that your results could contain personal data. Personal data is protected by the GDPR in the European Union and by other regulations around the world. You should not scrape personal data unless you have a legitimate reason to do so. If you're unsure whether your reason is legitimate, consult your lawyers.

You can also read Apify's blog post on the [legality of web scraping](https://blog.apify.com/is-web-scraping-legal/).

### Support

Questions, feature requests, or a field you'd like added? Reach out at <data.apify@proton.me> and we'll get back to you.

# Actor input Schema

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

Technologies, disciplines, or search handles to crawl, one per line (for example java, react, data, devops).

## `locationFilters` (type: `array`):

Trim results to specific cities, countries, or a remote keyword (for example Gdańsk, Wrocław, Remote). Accents and case are ignored.

## `resultsPerTerm` (type: `integer`):

Upper bound on how many adverts to keep for each term in the list.

## `timeoutSeconds` (type: `integer`):

How long to wait on a single request before giving up.

## Actor input object example

```json
{
  "searchTerms": [
    "java",
    "react",
    "data"
  ],
  "locationFilters": [
    "Gdańsk",
    "Wrocław",
    "Remote"
  ],
  "resultsPerTerm": 15,
  "timeoutSeconds": 45
}
```

# 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": [
        "java"
    ],
    "locationFilters": []
};

// Run the Actor and wait for it to finish
const run = await client.actor("data_api/nofluffjobs-scraper-cheap").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": ["java"],
    "locationFilters": [],
}

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

```

## MCP server setup

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

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "NoFluffJobs Scraper (Cheap)",
        "description": "NoFluffJobs Extractor that scrapes tech job postings and salary ranges from NoFluffJobs, so recruiters and market researchers can track hiring trends and benchmark salaries instantly.",
        "version": "0.0",
        "x-build-id": "NsvnkPPGOdNqzGlne"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/data_api~nofluffjobs-scraper-cheap/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-data_api-nofluffjobs-scraper-cheap",
                "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/data_api~nofluffjobs-scraper-cheap/runs": {
            "post": {
                "operationId": "runs-sync-data_api-nofluffjobs-scraper-cheap",
                "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/data_api~nofluffjobs-scraper-cheap/run-sync": {
            "post": {
                "operationId": "run-sync-data_api-nofluffjobs-scraper-cheap",
                "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",
                "required": [
                    "searchTerms"
                ],
                "properties": {
                    "searchTerms": {
                        "title": "Tech terms or categories",
                        "type": "array",
                        "description": "Technologies, disciplines, or search handles to crawl, one per line (for example java, react, data, devops).",
                        "items": {
                            "type": "string"
                        }
                    },
                    "locationFilters": {
                        "title": "Location filter (optional)",
                        "type": "array",
                        "description": "Trim results to specific cities, countries, or a remote keyword (for example Gdańsk, Wrocław, Remote). Accents and case are ignored.",
                        "items": {
                            "type": "string"
                        }
                    },
                    "resultsPerTerm": {
                        "title": "Adverts per term",
                        "minimum": 1,
                        "maximum": 1000,
                        "type": "integer",
                        "description": "Upper bound on how many adverts to keep for each term in the list.",
                        "default": 15
                    },
                    "timeoutSeconds": {
                        "title": "Request timeout (seconds)",
                        "minimum": 5,
                        "maximum": 120,
                        "type": "integer",
                        "description": "How long to wait on a single request before giving up.",
                        "default": 45
                    }
                }
            },
            "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
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
