InfoJobs Scraper - Spain Jobs, Salaries & Company Data API avatar

InfoJobs Scraper - Spain Jobs, Salaries & Company Data API

Pricing

from $5.33 / 1,000 results

Go to Apify Store
InfoJobs Scraper - Spain Jobs, Salaries & Company Data API

InfoJobs Scraper - Spain Jobs, Salaries & Company Data API

Scrape public InfoJobs job offers across all 52 Spanish provinces. Full job descriptions, structured salary ranges, contract type, working hours and remote-work flag. No API key.

Pricing

from $5.33 / 1,000 results

Rating

0.0

(0)

Developer

ParseForge

ParseForge

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

3 days ago

Last modified

Share

ParseForge

InfoJobs Scraper - Spain Jobs, Salaries & Company Data API

Scrape job offers from InfoJobs.net, Spain's largest job board, across all 52 provinces and 21 sectors. Every offer comes with the complete job description and a structured salary range — minimum, maximum, period and currency as separate numbers, not a string to parse. No login or API key. Export to CSV, JSON, Excel, or XML.

InfoJobs has no public API. This Actor reads the same data the website's own front end loads, which means the full description arrives with the listing — no second request per offer, and nothing that breaks when InfoJobs restyles a page. Turn on includeDetails and it also opens each offer page for the fields the listing never carries: how many people have applied, the required skills, the minimum experience and studies, and the normalised job title.

Who uses itWhat they scrape InfoJobs for
RecruitersWhich roles a Spanish province is hiring for right now, and who is posting them
Compensation analystsPublished pay ranges in EUR, split into gross yearly and monthly
Talent-intelligence teamsSalary benchmarks by sector, contract type and education level
Market researchersWhich companies are expanding into which Spanish regions
Remote-work platformsOffers flagged fully remote, hybrid or on-site

What it does

This Actor collects InfoJobs offers by keyword, province, sector and ten other filters, and returns each one as a flat row. Every offer carries:

  • 🧾 Core fields: title, company, city, contract type, working hours, and canonical offer URL.
  • 📄 The full job description — the entire posting text, not a truncated card summary.
  • 💰 Structured salary: salaryMin, salaryMax, salaryPeriod, salaryCurrency and salaryType as separate fields.
  • 📅 Exact dates: publishedAt as a real ISO 8601 timestamp, straight from InfoJobs.
  • 🚩 Flags: fully remote, promoted listing, executive role, and whether a salary is published at all.
  • 🏢 Employer: company name, its InfoJobs profile URL, and its logo.
  • 👥 Optional offer-page fields (includeDetails): applicants, vacancies, required skills, minimum experience and studies, seniority, industry, normalised job title and company rating.
  • 🔎 Several searches in one run: pass a list of keywords or of search URLs and get one deduplicated dataset.

Results export to CSV, JSON, Excel, or XML, or stream from the API.

What you can do with InfoJobs data

💰 Benchmark salaries across Spain.

Run the same job title in Madrid, Barcelona and Valencia, then compare salaryMin and salaryMax. Filter on hasSalary to drop the offers that publish no range, and always group by salaryPeriod — InfoJobs carries YEAR, MONTH and HOUR in the same field.

📈 Track hiring demand by province.

Scrape a sector on a schedule with sortBy: PUBLICATION_DATE and watch volume and freshness move week over week.

🏠 Map the remote-work market.

teleworking separates on-site, hybrid and fully remote. isRemote is true only for fully remote roles, so hybrid never inflates your remote counts.

🎯 Find companies that are actively hiring.

Group by companyName and sort by count. companyUrl links straight to the employer's InfoJobs profile.

👥 Measure how contested a job is.

With includeDetails, applicants tells you how many candidates already applied and vacancies how many seats there are. Sort ascending to find the openings nobody has found yet.

🧠 Build a skills map.

skills carries InfoJobs' own normalised skill list per offer, and normalizedTitle groups synonyms of the same role — the two fields that make sector-wide aggregation possible without string matching.

Why choose this scraper

What you get
Salary already splitsalaryMin, salaryMax, salaryPeriod, salaryCurrency and salaryType as separate fields. No string parsing, nothing to break when a symbol moves.
The description includedThe complete posting text ships with the listing page, so 100 full offers cost 100 rows — not 100 rows plus 100 detail requests.
Honest salary coveragehasSalary marks every row, and the measured coverage by search type is published below rather than hidden.
Filters by name, not IDMadrid, Indefinido, Solo teletrabajo — InfoJobs' own labels. An unknown value fails with the valid list instead of silently returning everything.
Strict remote flagisRemote is true only for Solo teletrabajo. Hybrid roles stay false, so remote counts stay honest.
Fields the listing hidesincludeDetails opens each offer page for applicants, vacancies, skills, experience, studies, seniority and the normalised title.
Salary filter InfoJobs lacksThe site has no minimum-salary filter — salaryMin returns HTTP 500. minSalary and maxSalary work here because the range is already structured, and monthly ranges are annualised by 12.
City-level searchcity narrows below the province, using InfoJobs' own city names. An unknown city fails with the list of cities that search really has, instead of returning zero rows in silence.
Several searches, one datasetkeywords or searchUrls fan out over many searches and deduplicate by offer ID.
Four export formatsCSV, JSON, Excel, and XML, from the dashboard or the API.

How it compares

Several InfoJobs scrapers exist and most return the same core fields. The difference is in the salary: the others publish "salary" as one value; this one splits it into five typed fields and tells you how often it is actually there.

The competitor columns below reflect what each Actor's own public listing states, not a test run of it. Prices and start fees were read from the Apify Store API on 19 August 2026; the start-fee row multiplies each Actor's published fee by its own default memory, because Apify charges one start event per gigabyte.

FeatureParseForgeeasyapialvaraazdelectable_incubatorcrawlerbros
Salary split into min / max / period / currency / typeYes, five fieldsNot statedOne "salaries" fieldOne "salary" fieldOne "salaries" field
hasSalary flag + published coverage figuresYesNoNoNoNo
Full job descriptionYesYesYesNot statedYes
Filters validated against InfoJobs' own vocabularyYes, 8 filtersNot statedNot statedNot statedNot stated
Fully-remote flag distinct from hybridYesNot statedNot stated"work mode"Not stated
Applicants per offerYes, applicantsNoNoNoNo
Normalised job title and skill listYesNoNoNoNo
Filter by minimum salaryYesNoNoNoNo
City-level filterYesNoNoNoNo
Price per result$0.00338$0.00299$0.0025$0.00198$0.002
Run-start fee at the Actor's own default memory$0.054$0.18none$0.0002$0.02

What an offer looks like

Every offer returns as one flat JSON row. Here is a real record, unedited apart from a trimmed description:

{
"offerId": "2b375a996045f9aa71b5f1b3f09e72",
"title": "Desarrollador LabVIEW",
"url": "https://www.infojobs.net/majadahonda/desarrollador-labview/of-i2b375a996045f9aa71b5f1b3f09e72",
"city": "Majadahonda",
"description": "DESARROLLADOR/A LabVIEW\nSomos ingenieros unidos por una vocación dedicada al diseño de control y automatización de sistemas...",
"companyName": "Murmann LabVIEW Consultants",
"companyUrl": "https://www.infojobs.net/murmann-labview-consultants/em-i98565551545250771171142016164387613158",
"companyLogo": "https://multimedia-logos.infojobs.net/image/upload/29/29846812-709a-482e-949f-e84a7b662cac",
"contractType": "Contrato indefinido",
"workday": "Jornada completa",
"teleworking": "Híbrido",
"isRemote": false,
"isPromoted": true,
"isExecutive": false,
"hasSalary": true,
"salaryMin": 25000,
"salaryMax": 33000,
"salaryPeriod": "YEAR",
"salaryCurrency": "EUR",
"salaryType": "GROSS",
"publishedAt": "2026-08-14T15:54:02Z",
"searchUrl": "https://www.infojobs.net/jobsearch/search-results/list.xhtml?keyword=desarrollador&provinceIds=33",
"scrapedAt": "2026-08-19T13:47:49.677Z",
"hasDetails": true,
"applicants": 45,
"vacancies": 1,
"minimumExperience": "Al menos 1 año",
"minimumStudies": "Diplomatura",
"seniority": "Empleado/a",
"industry": "Atención sanitaria y hospitalaria",
"subcategory": "Enfermería",
"normalizedTitle": "Enfermero/Enfermera",
"staffInCharge": 0,
"skills": ["Enfermería", "Emergencias", "Soporte vital avanzado"],
"companyRating": 3.43,
"companyRatingCount": 14
}

The block after scrapedAt only appears when includeDetails is on. hasDetails marks every row, so a missing field means InfoJobs did not publish it — not that the page went unread.

Offers without a published range carry hasSalary: false and no salary fields at all — they are not filled with zeros.

salaryPeriod is YEAR, MONTH or HOUR, exactly as the employer set it. It is passed through unchanged rather than normalised, so an obviously wrong one stays visible instead of being silently converted.

How much salary data you actually get

Salary coverage depends on how you search, so here are figures measured on real runs rather than a marketing number:

SearchOffers with a published range
Keyword search (desarrollador)~58–62%
Keyword plus province (desarrollador, Madrid)~56–58%
No keyword, everything open~32%

Searching by keyword roughly doubles salary coverage against browsing everything, because employers who write a targeted posting are the ones who also publish a range. Filter on hasSalary to keep only the offers that pay openly. Every run prints its own coverage in the log.

What the offer page adds

includeDetails opens the page of every offer it returns. That is one extra request per offer, so it is off by default and billed as a separate event. Coverage below was measured over 121 offers across seven searches in different sectors on 19 August 2026, and what is published is the spread between the best and the worst of those searches, not the best one:

FieldCoverageWhat it is
applicants100%How many candidates already applied
vacancies100%Seats the offer covers
minimumExperience100%Al menos 1 año
minimumStudies100%Diplomatura
seniority100%Empleado/a
subcategory100%InfoJobs' subcategory
normalizedTitle95–100%InfoJobs' normalised role name, which groups synonyms
industry76–100%Employer's industry, finer than the sector filter
staffInCharge71–100%People reporting to the role
skills67–95%Normalised skill list
companyRating / companyRatingCount15–70%Employee rating of the company
languages5–40%Required languages with level
benefits5–36%Social benefits
canApply100%Whether InfoJobs still accepts applications for the offer
minimumRequirements0–100%The advertiser's stated must-haves, in their words
industryId0–100%Numeric id behind industry, for joining against your own tables
department0–38%Hiring department
residentIn0–13%Whether residency in the area is required
referenceCode0–13%The advertiser's own reference, for matching against their ATS
desiredRequirements0–13%Nice-to-have requirements
workingHours0–13%Concrete hours, beyond the workday category

The last four vary by sector rather than by luck: hospitality offers published a company rating four times as often as accounting ones. hasDetails marks every row that was read, so an empty field there is a field InfoJobs does not publish for that offer.

The eight rows from canApply down were measured separately, over 40 offers across five searches on the same day, so their spread rests on a smaller sample than the rows above it. minimumRequirements is the one worth knowing about: it carries the advertiser's own must-haves and reaches every offer in some sectors while staying empty in others.

One field is deliberately left out. contractDuration exists on InfoJobs' offer pages but came back empty on all 53 offers inspected, so it is not published rather than shipped as an always-null column.

Offer pages multiply requests by 20. A run of 1,000 offers is 50 search pages without them and 1,050 requests with them. InfoJobs rate-limits by IP: while testing this Actor, a single unproxied IP started returning HTTP 403 after roughly 250 requests in half an hour, and the block cleared 3.8 minutes later. That is why the retries rotate the proxy session instead of waiting the block out — each attempt asks Apify Proxy for a different IP, which is the only remedy that works inside a run. Without a proxy the Actor stops with a clear error instead of writing half a dataset.

Coverage moves a lot with the search. Only the first eight fields are close enough to always-there to plan around; treat the rest as bonus and check them before building on one.

Configure the run

Drive the Actor with a keyword, twelve filters, or a raw InfoJobs search URL. The Input tab lists every parameter.

Search by keyword, newest first:

{ "keyword": "desarrollador", "sortBy": "PUBLICATION_DATE", "maxItems": 100 }

Narrow to a province and a contract type:

{ "keyword": "enfermero", "province": "Barcelona", "contractType": "Indefinido", "maxItems": 200 }

Every fully remote offer in a sector, published this week:

{ "category": "Informática y telecomunicaciones", "teleworking": "Solo teletrabajo", "sinceDate": "_7_DAYS", "maxItems": 500 }

Skip the descriptions to keep the dataset small:

{ "keyword": "camarero", "province": "Madrid", "includeDescription": false, "maxItems": 300 }

Several roles at once, deduplicated into one dataset:

{ "keywords": ["enfermero", "fisioterapeuta", "logopeda"], "province": "Madrid", "maxItems": 500 }

One city, only offers that pay above a threshold:

{ "keyword": "desarrollador", "city": "Barcelona", "minSalary": 35000, "maxItems": 200 }

Open every offer page for applicants, skills and experience:

{ "keyword": "data engineer", "province": "Madrid", "includeDetails": true, "maxItems": 100 }

Or paste a search URL straight from your browser — it overrides every filter above:

{ "searchUrl": "https://www.infojobs.net/jobsearch/search-results/list.xhtml?keyword=qa&provinceIds=33", "maxItems": 100 }

Filters take names, not IDs. province, category, contractType, workday, teleworking and education accept the same labels InfoJobs shows on its own filter panel — Madrid, Indefinido, Jornada completa, Solo teletrabajo. An unknown value fails immediately with the list of valid ones rather than silently returning the unfiltered search.

Pricing

Pay-per-event, so you are charged for the work the run actually does — and every charge lands after the row is written, never before.

EventPriceCharged
Actor start$0.054Once per run
Search query$0.009Once per keyword or search URL, and only once it has returned an offer
Result$0.00338 per offerPer row written to your dataset
Offer page details$0.00451 per offerOnly with includeDetails, and only when the page was actually read

Prices are the no-discount tier; Apify plan discounts take them down to $0.048, $0.00814, $0.003 and $0.004 on Gold. The event ids the API reports are apify-actor-start, search-query, result-item and result-details.

RunCost
100 offers, one search$0.40
1,000 offers, one search$3.44
1,000 offers with offer-page details$7.95
10,000 offers across five keywords$33.90

The full job description is included in the result price — no separate charge, and no second request. The start fee is charged once per gigabyte of Actor memory, and this Actor is capped at 1 GB, so the start fee you see on this page is the one you pay.

Free users

Free-plan runs return up to 100 offers as a preview. Upgrade your Apify plan to collect up to 50,000 offers per run and to get the volume discounts above.

New Apify accounts also come with $5 in credit, worth roughly 1,460 offers on a single search, or about 620 with offer-page details on.

A paid run is bounded by its timeout. Measured on the platform: 100 offers in 36 seconds without offer pages and 60 in 121 seconds with them, so the default 900-second timeout holds about 2,400 offers listing-only and about 440 offers with includeDetails on, because that turns every offer into its own request. Raise the timeout in the run options for a bigger job, or split it across scheduled runs.

Run it

  1. Create a free Apify account with $5 in credit.
  2. Open the InfoJobs Scraper.
  3. Type a keyword, optionally pick a province or city, set maxItems, and click Start.
  4. Export the results as CSV, Excel, JSON, or XML from the Dataset tab.

Run it programmatically through the Apify API or the ApifyClient for JavaScript and Python.

Use with AI agents (MCP)

Give an AI agent live access to InfoJobs through the Model Context Protocol. Add the Actor to Claude, Cursor, or any MCP client:

$claude mcp add --transport http apify "https://mcp.apify.com?tools=parseforge/infojobs-scraper"

Then prompt it in plain language:

  • "Find developer jobs in Madrid posted this week that publish a salary."
  • "Compare published salaries for nurses in Barcelona, Valencia and Sevilla."
  • "Pull the 200 newest fully remote offers in Spain and rank the companies by how many applicants they already have."

Copy this into ChatGPT, Claude, or Cursor to start:

Use the Apify Actor "parseforge/infojobs-scraper" to collect public InfoJobs.net job offers from Spain. Input: { "keyword": "<role>", "keywords": ["<role>", "<role>"], "province": "<Spanish province name, e.g. Madrid>", "city": "<InfoJobs city name, e.g. Barcelona>", "category": "<optional sector>", "contractType": "<optional>", "teleworking": "<Presencial|Híbrido|Solo teletrabajo|Sin especificar>", "segment": "<Executive>", "minSalary": <euros per year>, "maxSalary": <euros per year>, "sinceDate": "<ANY|_24_HOURS|_7_DAYS|_15_DAYS>", "sortBy": "<RELEVANCE|PUBLICATION_DATE>", "includeDetails": <true to open each offer page>, "maxItems": <n> }. It returns offerId, title, url, city, the full description, companyName, companyUrl, contractType, workday, teleworking, isRemote, hasSalary, salaryMin, salaryMax, salaryPeriod, salaryCurrency, salaryType and publishedAt per offer, plus applicants, vacancies, skills, minimumExperience, minimumStudies, seniority, industry, normalizedTitle and companyRating when includeDetails is true. Filters take InfoJobs' own Spanish labels, not numeric ids. Call it with the ApifyClient and my APIFY_TOKEN.

Troubleshooting

Why am I getting no results?

The filter combination may have no matches. Drop province first, then category, and confirm the keyword alone returns offers. The run log prints the search URL — open it in a browser to see exactly what InfoJobs sees.

Why did my province name get rejected?

province takes InfoJobs' own spelling, including the bilingual ones — Valencia/València, Alicante/Alacant, Vizcaya/Bizkaia. The error message lists valid values. Only the 52 Spanish provinces are offered; for offers abroad, use onlyForeignCountry or paste a searchUrl.

Why fewer offers than I asked for?

maxItems is a ceiling, not a target. The search ran out — InfoJobs returns 20 offers per page, sometimes 22 when it inserts promoted ones, and a narrow search often holds only a handful of pages. Widen it, or drop a filter.

Why is salaryMin empty?

That offer publishes no salary. Roughly a third to two thirds do, depending on how you search — see the table above. Filter on hasSalary to keep only the ones that do.

Why is description empty?

includeDescription is off. Turn it back on; it costs no extra requests.

Why is applicants — or any other offer-page field — empty?

Check hasDetails. If it is false, includeDetails was off and the offer page was never opened. If it is true, the page was read and InfoJobs simply publishes nothing for that field on that offer — see the coverage table above.

My city returned nothing.

An unknown city gives InfoJobs zero results rather than an error, so the run fails on purpose with the list of cities that search actually holds. Use the site's own spelling — Santa Cruz de Tenerife, not santa-cruz-de-tenerife — though capitals and accents do not matter. city narrows inside whatever province you set, so a mismatched pair returns nothing.

The salary filter dropped everything.

minSalary and maxSalary can only match offers that publish a range, and roughly a third to two thirds do. Offers priced by the hour are excluded too, because an hourly rate cannot be turned into a yearly figure without inventing an assumption. The run log prints how many rows the filter dropped.

Why is the run slow?

Each page holds 20 offers, so a large maxItems fetches many pages, and includeDetails adds one request per offer on top. InfoJobs also rate-limits by IP, and a retried page adds backoff delay. Lower maxItems, turn includeDetails off, or split the job across scheduled runs.

I got HTTP 403.

That is InfoJobs' rate limiter, not a ban. It was measured clearing in under four minutes. Each retry inside the run asks Apify Proxy for a fresh IP, so leave the proxy on; if you are running without one, wait a few minutes and lower maxItems or turn includeDetails off.

A field stopped filling.

InfoJobs changed its front end. Email us with your run ID so we can update the parser.

FAQ

QuestionAnswer
Do I need an InfoJobs account or API key?No. This reads public search pages, so there is nothing to register or authorize.
Which regions does it cover?All 52 Spanish provinces across 21 sectors. Offers outside Spain are reachable with onlyForeignCountry or a pasted searchUrl.
Does it return the full job description?Yes, the complete posting text, at no extra cost and with no second request. Turn it off with includeDescription if you want a smaller dataset.
Does it return salary data?Yes, already split into salaryMin, salaryMax, salaryPeriod, salaryCurrency and salaryType. Coverage runs about 32% to 62% depending on the search.
Why do some salaries look small?They are monthly or hourly, not yearly. salaryPeriod carries YEAR, MONTH or HOUR — always group by it before comparing.
Can I trust salaryPeriod?It is what the employer selected on InfoJobs, passed through unchanged. Most are right, but a few are not — we have seen a 33000–36000 EUR range tagged HOUR. Treat an hourly range in the thousands as an annual figure that was mislabelled.
What is isRemote?True only for offers InfoJobs marks "Solo teletrabajo". Hybrid roles are false, so remote counts stay honest. Use teleworking for the three-way split.
Can I filter by contract type or education?Yes. Twelve filters in total: province, city, country, sector, contract type, working hours, remote mode, education level, segment, publication window, salary range, and foreign-country only. That is every filter dimension InfoJobs itself honours — its own search panel exposes no others that change the result set.
Can I search several roles in one run?Yes. keywords takes a list and runs one search per entry, searchUrls does the same with pasted URLs, and both deduplicate by offer ID. Each search is charged as one search query, and only after it has actually returned an offer.
What does applicants mean?How many candidates have applied to that offer, as InfoJobs publishes it on the offer page. It needs includeDetails, and it was present on every offer measured.
Does includeDetails cost extra?Yes — one extra request per offer, billed as result-details. It is off by default, and a row is only charged for it when the page was actually read.
How many offers per run?Free plan: 100. Paid: up to 50,000, bounded by how many offers the search actually holds and by the run timeout. Measured on the platform on 19 August 2026: 100 offers in 36 seconds without offer pages and 60 in 121 seconds with them, so the default 900-second timeout holds roughly 2,400 offers listing-only or about 440 offers with includeDetails on. An unfiltered search held 57,251 offers across 2,863 pages, and page 1,000 still returned fresh offers, so the ceiling is the clock, not the site.
Do I need a proxy?Yes, and Apify Proxy is on by default. InfoJobs rate-limits by IP: an unproxied IP was measured returning HTTP 403 after about 250 requests in half an hour. It matters most with includeDetails, which turns every offer into its own request.
Is this an official InfoJobs product?No. It is unofficial and reads only public InfoJobs data.

Browse the full ParseForge collection for more scrapers.

🆘 Need help? Email parseforge@protonmail.com with your run ID, your input, and what you expected.

⚠️ Disclaimer. This Actor is unofficial and is not affiliated with, endorsed by, or sponsored by InfoJobs or Grupo Adevinta. It collects only publicly available InfoJobs data. You are responsible for using the data in compliance with InfoJobs' terms and applicable laws, including GDPR. Do not use it to identify, profile, or target individuals.