solid.jobs Polish IT Jobs Scraper: Poland, Salary in PLN
Pricing
from $1.00 / 1,000 jobs
solid.jobs Polish IT Jobs Scraper: Poland, Salary in PLN
IT job offers from solid.jobs, Poland. Salaries converted to PLN per month, contract tagged UoP or B2B. Filter by keyword, city, level, contract, remote and minimum salary. Only-new mode for scheduled alerts. Optional AI fit score. Pay per job after filters.
Pricing
from $1.00 / 1,000 jobs
Rating
0.0
(0)
Developer
Solid Fetch
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 days ago
Last modified
Categories
Share
Get IT job offers from solid.jobs, a Polish IT job board, as a clean feed or an API. Every salary is converted to PLN per month, with EUR and USD equivalents, and the contract is tagged UoP or B2B. Filter by keyword, city, level, category, contract type, remote, only offers with a salary and minimum salary, sort by newest or best paid, and pay only for the jobs that pass the filters. Schedule it with only-new mode for a daily alert. The data comes from the public API of solid.jobs and covers only that board.
What people use it for
- A job search feed with real filters. One list of React, Python or .NET jobs from solid.jobs, already filtered to B2B in Warsaw from 20,000 PLN a month, with the link to each offer.
- Daily alerts. Schedule the same search every morning with
onlyNewSinceLastRunand get only offers that are new or whose salary, contract or title changed. Unchanged offers are skipped and cost nothing. - Recruiting and market research. Salary ranges per technology, level, city and contract type, normalised to one unit, for hiring plans, salary benchmarks or lead lists of companies that are hiring.
- Salary benchmarks without a spreadsheet. Set
modetosalaryReportand get one row per technology and experience level (or city, contract, category) with offer counts and PLN and EUR monthly salary percentiles, B2B and UoP kept apart. See Salary report mode. - An AI shortlist (optional). Describe the candidate in a few lines and each job gets a fit score from 0 to 100, a verdict and short reasons, after the hard filters have already removed what does not fit.
How to use it
- Type keywords (any of them can match), cities and the filters you need. All fields are optional: an empty input returns the newest IT offers from solid.jobs.
- Run it and download the results as JSON, CSV or Excel, or read them through the API.
- For alerts, save the input as a task, turn on Only new or changed since the last run and add a schedule.
{"keywords": ["React", "Next.js"],"cities": ["Warsaw"],"contractTypes": ["B2B"],"minSalaryPln": 20000,"experienceLevels": ["mid", "senior"],"publishedWithinDays": 14,"maxItems": 200}
How the filters work
- Keywords are OR: a job matches when its title or skills contain any of them. Spelling variants count as the same word, for example
front-end,front endandfrontend, orReact.js,ReactJSandReact, orJSandJavaScript.C#and.NETare matched as written. Words match whole, soJavadoes not matchJavaScript. SetkeywordsIntotitlefor title-only matching, or toeverythingto search descriptions too. - Cities accept Polish and English names: Warszawa or Warsaw, Kraków, Krakow or Cracow, Wrocław, Łódź, and Trójmiasto for Gdańsk, Gdynia and Sopot. Fully remote jobs pass the city filter. Turn on
remoteOnlyto keep only those. - Contract types are
UoP(umowa o pracę),B2Bandother(umowa zlecenie, o dzieło, internships). An offer whose contract is not stated is dropped when you pick a contract type. - Minimum salary compares the top of the salary range, in PLN per month, for the contract types you picked. Hourly rates count 168 hours a month, daily rates 21 days, and other currencies use the National Bank of Poland rate of the day. Offers without a salary are dropped when this filter is set. B2B amounts are usually net and UoP amounts gross, and the
grossfield on each salary says which. - Categories are solid.jobs' own:
Developer,DevOps,DataScience,Tester,Analyst,Architect,ItManager,UXUIDesigner,Security,Support,Administrator,OtherIT, or a specialisation such asReact,Java,Python,DotNet,Angular,ProjectManager. A job passes when itscategoryorsubCategoryis in your list; case and punctuation do not matter, soUX/UI Designerworks. The list is read from recorded offers, so the board may have more. - Only jobs with a salary (
withSalaryOnly) drops offers that state no salary, without asking for a minimum. - Order (
sortBy) isnewest(default) orsalary, the top of the salary range in PLN per month for the contract types you picked, offers without a salary last. Best paid first needs every offer before it can pick the top ones, so the actor reads all pages of the board (about four requests of 500, still one every 500 ms) instead of stopping early; the run takes a few seconds longer. - Excluded companies and words remove offers from companies you already applied to, or titles with words like
SeniororAngular. Legal suffixes such assp. z o.o.do not matter.
Every filter runs before anything is saved or charged, and expired offers are always removed. A field the actor does not know rejects the run with an error, so a typo such as keyword instead of keywords cannot turn into a run of unfiltered jobs.
Salary report mode
Set mode to salaryReport to get aggregates instead of single offers. The actor reads the offers exactly as in the job list, with the same filters (keywords, cities, experienceLevels, contractTypes, remoteOnly, publishedWithinDays, categories, minSalaryPln, withSalaryOnly, excludeKeywords, excludeCompanies), and saves one row per group.
{"mode": "salaryReport","groupBy": ["technology", "experienceLevel"],"minOffers": 5,"cities": ["Warsaw"],"publishedWithinDays": 60}
groupBy: any oftechnology(also accepted asskill),city,experienceLevel,contractType,category. Default:technologyandexperienceLevel.minOffers: groups with fewer offers are left out and counted in the run summary. Default 3.- A report reads every offer that passes the filters.
maxItems,sortByandincludeDescriptionare ignored, andprofile(AI score) andonlyNewSinceLastRunare rejected.
A row built from the solid.jobs responses recorded on 3 October 2026 (groupBy left at the default, so the row is mid-level offers that require SQL):
{"technology": "SQL","experienceLevel": "mid","offers": 10,"withSalary": 10,"b2bOffers": 9,"b2bPlnMin": 11350,"b2bPlnP25": 19300,"b2bPlnMedian": 21000,"b2bPlnP75": 23550,"b2bPlnMax": 26050,"b2bEurMin": 2595,"b2bEurP25": 4412,"b2bEurMedian": 4801,"b2bEurP75": 5383,"b2bEurMax": 5955,"uopOffers": 1,"uopPlnMin": 12500,"uopPlnP25": 12500,"uopPlnMedian": 12500,"uopPlnP75": 12500,"uopPlnMax": 12500,"uopEurMin": 2857,"uopEurP25": 2857,"uopEurMedian": 2857,"uopEurP75": 2857,"uopEurMax": 2857,"sampleOfferUrls": ["https://solid.jobs/o/3tzqfew5/solidfetch", "https://solid.jobs/o/rkflekzk/solidfetch", "https://solid.jobs/o/477a7jop/solidfetch"]}
| Field | Description |
|---|---|
technology, city, experienceLevel, contractType, category | The group keys you chose in groupBy, and only those. |
offers | Offers in the group. An offer with several skills, cities or levels counts in each of its groups. Copies of one offer count once. |
withSalary | Offers in the group with a B2B or UoP salary. |
b2bOffers, uopOffers | Offers with a B2B (net) or UoP (gross) salary. The two are never blended: B2B and UoP figures are separate columns. |
b2bPlnMin, b2bPlnP25, b2bPlnMedian, b2bPlnP75, b2bPlnMax | Minimum, 25th percentile, median, 75th percentile and maximum of the midpoint of each offer's salary range, PLN per month. The same five fields with the uop prefix for UoP. null when no offer in the group has that salary. |
b2bEurMin ... b2bEurMax, uopEurMin ... uopEurMax | The same figures in EUR at the National Bank of Poland rate of the run. null when the rates were unavailable. |
sampleOfferUrls | Up to 3 offers of the group, those with a salary and the newest first. |
How the numbers are made:
- Midpoint. An offer with 20,000 to 24,000 PLN counts as 22,000. Hourly, daily and foreign-currency salaries are converted to PLN per month first, like in the job list.
- Technology means the technologies an offer marks as required, with spelling variants merged (
React,React.js,ReactJS). Nice-to-have skills are not counted. City is every city of the offer, category is solid.jobs' own category. - Contract types. Only B2B and UoP salaries are summed up; a salary under
otheris not in the report. WithcontractTypesset, only those contracts count, also for an offer that states both. Grouped bycontractType, a group counts only its own contract. - Offers without a value for a chosen key (for example no city) are left out, and the run message says how many.
- Small groups. A group with 3 offers and one salary still gets a row; read
withSalary,b2bOffersanduopOffersbefore trusting a median. - The run message and the
REPORT_SUMMARYrecord in the key-value store give the totals: offers read, offers with a salary, groups, rows built (rows) and saved (rowsSaved), and groups left out forminOffers. If solid.jobs failed part way, the message says the report is built on part of the offers. - Maximum cost. Once report rows are charged, a run with a maximum cost saves as many rows as it covers, the groups with the most offers first, and says so in the message (
stoppedByChargeLimitinREPORT_SUMMARY).
Output
A row built from a solid.jobs response recorded on 3 October 2026 (keywords: ["Python"], includeDescription: false, so description is empty):
{"id": "solidjobs:bf935ae2-400a-4cb4-a72a-494368ace488","source": "solidjobs","url": "https://solid.jobs/o/h2xptmo5/solidfetch","title": "Senior Test Automation Engineer","company": "DCG","cities": ["Warszawa"],"remote": false,"workplace": "hybrid","contractTypes": ["B2B"],"salaryMin": 21000,"salaryMax": 22700,"salaryCurrency": "PLN","salaryPeriod": "month","salaryContract": "B2B","salaryPlnMonthlyMin": 21000,"salaryPlnMonthlyMax": 22700,"salaryEurMonthlyMin": 4801,"salaryEurMonthlyMax": 5189,"salaryUsdMonthlyMin": 5401,"salaryUsdMonthlyMax": 5838,"salaries": [{ "contract": "B2B", "min": 21000, "max": 22700, "currency": "PLN", "period": "month", "gross": false, "plnMonthlyMin": 21000, "plnMonthlyMax": 22700, "eurMonthlyMin": 4801, "eurMonthlyMax": 5189, "usdMonthlyMin": 5401, "usdMonthlyMax": 5838 }],"seniority": ["senior"],"skills": ["Python", "Robot Framework", "SQL"],"requiredSkills": [{ "name": "Python", "level": "advanced" },{ "name": "Robot Framework", "level": "advanced" },{ "name": "SQL", "level": "advanced" }],"niceToHaveSkills": [],"category": "Tester","subCategory": "TestAutomationEngineer","companyLogoUrl": "https://cdn.solid.jobs/companies/logos/eab6a3169f974c89aebe723c4f6c901f.jpeg","benefits": [],"languages": [{ "name": "Angielski", "level": "advanced" }],"publishedAt": "2026-09-30T09:12:50.878Z","expiresAt": "2026-10-31T09:12:50.878Z","description": null,"alsoListedOn": [],"changeType": null,"firstSeenAt": null}
| Field | Description |
|---|---|
id | Stable ID: solidjobs plus the offer ID on solid.jobs. |
source, url | Always solidjobs, and the offer page on solid.jobs. |
alsoListedOn | Other listings of the same offer, for example a copy for another city, merged into this row and not charged again. Usually empty. |
cities, workplace, remote | All cities of the offer, and remote, hybrid or office. |
contractTypes | UoP, B2B, other. Empty when the board does not say. |
salaryMin, salaryMax, salaryCurrency, salaryPeriod, salaryContract | The best salary of the offer as the board states it (for the contract types you filtered on). |
salaryPlnMonthlyMin, salaryPlnMonthlyMax | The same salary in PLN per month. |
salaryEurMonthlyMin, salaryEurMonthlyMax, salaryUsdMonthlyMin, salaryUsdMonthlyMax | The same salary in euro and US dollars per month, at the National Bank of Poland rate of the run (table A, one request per run). null when that request failed; the run message says so and the run does not fail. |
salaries | Every salary of the offer, one per contract type, with the PLN monthly values and gross. |
seniority | intern, junior, mid, senior, lead. |
skills | Required and nice-to-have technologies together, names only. |
requiredSkills, niceToHaveSkills | The same split: required technologies with level (basic, advanced, expert, or null), and the names of the nice-to-have ones. |
category, subCategory | solid.jobs' category (Developer, DevOps, Tester...) and specialisation (React, Java...). |
companyLogoUrl | Link to the company logo on the solid.jobs CDN. |
benefits | Benefits as solid.jobs lists them, in Polish, for example Pakiet medyczny. |
languages | Spoken languages the offer asks for, in Polish as the board names them (Angielski), with level basic, advanced, expert or niceToHave. |
publishedAt, expiresAt | Publish date as the board shows it (a refreshed offer counts from the refresh) and the end date. |
description | Plain text, up to 6,000 characters. Long descriptions keep the beginning and the end, where requirements usually are. null when includeDescription is off. |
changeType, firstSeenAt | With onlyNewSinceLastRun: new or updated, and when the actor first saw the offer. |
fitScore, verdict, reasons, requiredYears, hardStops, aiError | Only with a profile, see below. |
The SOURCES_STATUS record in the run's key-value store lists solid.jobs with the number of offers listed, saved, and dropped by each filter, and gives it a status: ok, noMatches, partial (stopped part way, the jobs read before the error are kept), blocked or failed, with the reason. The run log prints the same lines.
AI fit score (optional)
Write a short profile: years of experience, stack, level, wanted salary and contract, city or remote, deal-breakers. Each job that passed the filters then gets:
fitScorefrom 0 to 100,verdict:match,maybeorno,reasons: two to four short sentences,requiredYears: the minimum years of experience the offer asks for, ornull,hardStops: requirements the candidate fails, such as "asks for 5+ years, candidate has 2".
The model sees only jobs that passed the filters, so the score is spent on real candidates. Scoring uses your own API key (llmProvider and llmApiKey) for Anthropic (Claude Haiku), OpenAI (GPT-5 nano) or Google (Gemini Flash-Lite). Without a key the run stops at the start and says so, so set the key or remove profile. The key is a secret input: Apify stores it encrypted, and the actor sends it only to your provider and does not write it to the log or the results. If the model answers with something that is not a valid score, the job is still saved with aiError and is not charged for scoring. maxAiScores (default 200) caps the number of scored jobs per run.
Ready-made searches
Open one of these, change the input and run it:
- React developer jobs in Warsaw from solid.jobs
- Remote IT jobs in Poland
- Polish B2B IT jobs above a minimum salary
- Junior and intern IT jobs in Poland from the last week
- Alert for new IT jobs in Poland
Send results to Make, Zapier, n8n or a CRM
Long runs do not need to keep a Make or Zapier scenario waiting:
- Start the actor or one of its saved tasks on a schedule, or from your scenario with the asynchronous "Run Actor" step.
- Trigger the next step on the finished run. In Make use the Apify module "Watch Actor Runs", in Zapier the Apify trigger for a finished actor run, in n8n the Apify node.
- Read the rows with "Get Dataset Items" using the run's dataset ID.
For your own endpoint, open the actor's Integrations tab and add an HTTP webhook on "Run succeeded". Apify retries failed deliveries, and the payload contains resource.defaultDatasetId, which you can read at https://api.apify.com/v2/datasets/<datasetId>/items?format=json. Add &format=csv for a spreadsheet, or &flatten=<field> to turn nested objects into flat columns.
Pricing
You pay per job saved, after filters, duplicate merging and expired-offer removal:
| Event | Free and Bronze | Silver | Gold and above |
|---|---|---|---|
| Job saved | $2.00 per 1,000 | $1.50 per 1,000 | $1.00 per 1,000 |
| AI fit score (you pay your LLM provider directly) | free | free | free |
Salary report row (mode: salaryReport) | free until 4 November 2026, then $0.01 | $0.008 from 4 Nov | $0.006 / $0.005 (Gold) from 4 Nov |
Salary report rows are free until 4 November 2026; from then on each report row (one group) is charged once, and the offers read for the report are never charged as jobs. A run also has a start fee of $0.00005 per run start (per GB of memory). There is no extra charge for platform usage. A run that finds nothing costs only the start fee, merged duplicates and unchanged offers in scheduled runs are free, and the run stops on its own at the maximum cost you set. If the platform migrates or restarts a run, the jobs saved before are not saved or charged again, and they still count toward maxItems.
FAQ
Which board and how many offers? Only solid.jobs. On 3 October 2026 it listed 1,651 IT offers through its public API. The actor reads that API, up to 500 offers per request, and stops when it has enough matches (with sortBy set to salary it reads them all first). It sends a campaign name with every request, as solid.jobs asks, and waits between requests to stay far below the limit of 300 requests a minute.
What happened to NoFluffJobs, bulldogjob.pl and justjoin.it? They are no longer read, because their terms do not allow automated downloading. Saved tasks and API calls that still send sources with those names keep working: the names are dropped with a warning in the run log and the run uses solid.jobs. The old sources and proxyConfiguration fields are accepted and ignored. Because the search memory of only-new mode no longer depends on the board list, the first scheduled run after this change returns the matching offers once more.
Why fewer jobs than solid.jobs shows? maxItems limits each run (default 100, up to 5,000), and the actor stops reading once it has enough matching offers. Merged duplicates count once.
How fast is it? In test runs from Poland, 30 to 40 filtered jobs with descriptions took 2 to 15 seconds, and 300 jobs took about 100 seconds. Offers come with their descriptions in the list itself, so includeDescription mostly changes the size of the result.
Does it need a login or cookies? No. The solid.jobs public API is read without an account.
Can I filter by salary when a job pays per hour or in euro? Yes. The minimum salary compares the PLN monthly value, so 150 PLN per hour (25,200 PLN a month) passes a 25,000 PLN minimum.
Can I use it from code or an AI agent?
curl -X POST "https://api.apify.com/v2/acts/solidfetch~poland-it-jobs/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-H "Content-Type: application/json" \-d '{"keywords": ["Python"], "remoteOnly": true, "maxItems": 50}'
It also works through the Apify MCP server in Claude, Cursor and other agents, and with the Apify integrations for Make, n8n, Zapier and Google Sheets.
Limits
- One board. The actor covers solid.jobs only, which lists fewer offers than all Polish boards together. Pracuj.pl, LinkedIn and others are not included.
- Fields solid.jobs does not give. There is no apply link other than the offer page (
url), and no company website, company size, office coordinates or daily tasks in its public API, so the rows do not have them. Recruiter names, e-mails and phone numbers are never collected. - EUR and USD are a conversion, not the board's figure. They use the National Bank of Poland mid rate of the last working day, applied to the monthly PLN amount.
- Contract and salary come from solid.jobs. Some offers state no contract or no salary. Those rows have an empty
contractTypesor no salary. - Publish dates are solid.jobs' own. A refreshed offer shows the refresh date.
- The AI score is an opinion of a small, cheap model. It reads the description and the profile and can be wrong. Use it to sort a list, not to reject candidates.
- If solid.jobs changes its API format, the run reports the board as
failedwith the reason instead of ending as an empty success. Found a problem? Open an issue on the actor page with the input you used.
When a run fails, an error report with the error message and the shape of the input (which fields are set, how long the lists are), never your input values, profile, API key or results, is sent to the developer to fix bugs.
This is an independent tool and is not affiliated with solid.jobs.
If this actor saved you time, a short review on the actor page helps other people find it.