Wallapop Scraper [$0.80/1K💰] | ES, PT & IT Listings avatar

Wallapop Scraper [$0.80/1K💰] | ES, PT & IT Listings

Pricing

from $0.80 / 1,000 results

Go to Apify Store
Wallapop Scraper [$0.80/1K💰] | ES, PT & IT Listings

Wallapop Scraper [$0.80/1K💰] | ES, PT & IT Listings

Scrape Wallapop secondhand listings across Spain, Portugal and Italy. Get title, price, condition, category, seller type, location, photos, shipping, view and favourite counts. Geo-targeted keyword search with optional detail enrichment.

Pricing

from $0.80 / 1,000 results

Rating

0.0

(0)

Developer

Ahmed Jasarevic

Ahmed Jasarevic

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

a month ago

Last modified

Categories

Features

Limited permissions

Share

Wallapop Scraper — Secondhand Listings Across Spain, Portugal and Italy

Extract Wallapop listings — the leading secondhand marketplace in Spain and one of the largest in Southern Europe — with title, price, condition, category, seller type, location, photos, shipping flags, view and favourite counters.

Keyword search across ES, PT and IT, geo-targeted to the coordinates you choose, with optional detail enrichment. Built for price monitoring, resale arbitrage research, competitive pricing, market-entry analysis and secondhand inventory data.


The one header nobody else sets

Wallapop's search API 403s every request that does not send X-Platform: web. It is a single header, and it is mandatory — without it, a scraper that is otherwise perfectly written returns nothing at all. This Actor sends it on every request.

That is the difference between a Wallapop scraper that works and one that returns an empty dataset on day one.


What you get that makes cross-country analysis possible

Wallapop changes its interface language per market — Como nuevo in Spain, Como novo in Portugal, Come nuovo in Italy. Sorting or grouping on the localized label means three different vocabularies that do not match.

This Actor returns condition and conditionValue together: the localized label and a stable machine slug that does not change with the front-end language. One group-by works across all three markets.

Also included, because they decide whether a listing is actionable:

  • sellerType — professional or private, which separates genuine consumer resale from business inventory
  • isReserved / isRefurbished / hasWarranty — availability and refurbishment flags
  • views / favorites / conversations — real engagement counters: how much interest a listing actually draws
  • ageDays — listing age computed at scrape time, so "new arrivals" is a filter, not a guess
  • sellerLocation with full coordinates, city, region and postal code
  • _summary — a run-level record with totals, unique listing count and whether detail enrichment ran

Main use cases

  • Secondhand price monitoring — track prices for a product category in a city, week over week
  • Resale and arbitrage research — find underpriced stock before it sells, compare professional vs private sellers
  • Competitive pricing — see what a product sells for across three countries at once
  • Market entry analysis — measure secondhand market depth and saturation in Spain, Portugal or Italy before launching
  • New-arrival detection — ageDays plus postedAt makes "just listed" a filter, not a manual sort
  • Sourcing leads — seller type, location and engagement on high-view listings surface the best counterparty candidates
  • Category and assortment research — category taxonomy plus the price distribution of live inventory
  • Listing quality benchmarking — use views and favorites per ageDays as an engagement benchmark

Input

FieldTypeRequiredDefaultNotes
keywordsarrayno["iphone 14"]Search keywords. One search run per keyword.
startUrlsarrayno[]Wallapop URLs. /search?keywords=... URLs are converted into API requests; /item/<id>/<slug> URLs are fetched detail-only. Use instead of keywords.
countrystringnoESES, PT or IT. Sets the default coordinates and Accept-Language.
latitudenumbernocountry defaultOverride latitude (e.g. 41.3874 for Barcelona).
longitudenumbernocountry defaultOverride longitude (e.g. 2.1686 for Barcelona).
minPricenumberno—Only listings at or above this price (EUR).
maxPricenumberno—Only listings at or below this price (EUR).
orderBystringnomost_relevancemost_relevance, newest or closest.
maxItemsintegerno40Max listings per keyword or search URL. Capped at 1000. Free-plan users are limited to 10 per run.
enrichWithDetailsbooleannotrueFetch api/v3/items/<id> per listing. Required for condition, seller type, engagement counters and warranty flags. Turning it off roughly halves the requests.
includeReservedbooleannofalseWhen false, listings already marked reserved are skipped.
maxRequestsPerCrawlintegerno1000Hard cap on total HTTP requests for the run.
proxyobjectnouseApifyProxy: falseStandard Apify proxy picker. Not needed — the first-party API does not block.

Default coordinates per country

Wallapop results are geo-targeted, so the coordinates decide which listings come back.

countryDefault pointLanguage
ESMadrid (40.4168, -3.7038)es-ES
PTLisbon (38.7223, -9.1393)pt-PT
ITRome (41.9028, 12.4964)it-IT

Always override the coordinates for a specific city. Searching "iphone 14" with the Madrid default returns Madrid-area results, not Barcelona's.

Examples

City price sweep in Barcelona, detailed:

{
"keywords": ["iphone 14", "iphone 15"],
"country": "ES",
"latitude": 41.3874,
"longitude": 2.1686,
"maxItems": 200,
"orderBy": "most_relevance"
}

Cheapest possible run — search payload only, no per-item detail calls:

{
"keywords": ["bicicleta"],
"country": "ES",
"latitude": 41.3874,
"longitude": 2.1686,
"enrichWithDetails": false,
"maxItems": 500
}

New arrivals in Lisbon, reserved excluded, price-banded:

{
"keywords": ["portatil"],
"country": "PT",
"latitude": 38.7223,
"longitude": -9.1393,
"minPrice": 100,
"maxPrice": 800,
"orderBy": "newest",
"includeReserved": false,
"maxItems": 300
}

Cross-border price comparison for one product:

{
"keywords": ["playstation 5"],
"startUrls": [
"https://wallapop.com/search?keywords=playstation%205",
"https://wallapop.com/search?keywords=playstation%205&latitude=41.3874&longitude=2.1686"
],
"enrichWithDetails": true,
"maxItems": 150
}

Detail-only on known listing URLs:

{
"keywords": [],
"startUrls": [
"https://wallapop.com/item/123456789/iphone-14-pro-256gb"
],
"enrichWithDetails": true
}

Output

One dataset — one row per listing. The Listings view gives you title, price, currency, condition, category, seller, city, country, posted date, age in days, shipping, views, favorites and the listing link.

Listing identity

FieldDescription
idWallapop item ID — the stable join key
titleListing title
descriptionFull listing description
url / listingUrlCanonical listing page URL
shareUrlWallapop's own share link, if the seller set one

Price and condition

FieldDescription
pricePrice as a number
currencyCurrency code, normally EUR
conditionLocalized condition label, e.g. Como nuevo, Buen estado
conditionValueStable machine slug for the same condition, e.g. as_good_as_new
isRefurbished / hasWarrantyRefurbished and warranty flags

condition + conditionValue is the pair that makes cross-country analysis work. Group on conditionValue — the labels change between the Spanish, Portuguese and Italian front ends, the slugs do not.

Category

FieldDescription
categoryLeaf category name
categoryPath[]Full taxonomy path from root to leaf
categoryId / itemTypeTaxonomy identifiers and item type

Seller

FieldDescription
sellerIdSeller account ID
sellerTypeprofessional or private
bumpWhether the listing is promoted, and how

Location

FieldDescription
sellerLocation.city / .region / .country / .postalCodeSeller location
sellerLocation.latitude / .longitudeCoordinates

Dates and availability

FieldDescription
postedAtISO publish timestamp
postedAtMsRaw epoch milliseconds
updatedAtISO last-modified timestamp
ageDaysAge in days, computed at scrape time
isReservedWhether the listing is already reserved

Engagement

FieldDescription
viewsView count
favoritesFavourite count
conversationsMessage-thread count

Media and shipping

FieldDescription
photos[]Full-size photo URLs
photoCountNumber of photos
shipping / itemIsShippableWhether the item can be shipped
supportsShippingShipping support flag from the detail record
characteristicsFree-text characteristics line
characteristicsDetails[]attribute / value pairs from the detail record

Provenance and run summary

FieldDescription
queryThe keyword or search that produced this row
countryTarget marketplace (ES / PT / IT)
scrapedAtISO timestamp
_summary.totalListingsTotal listings collected in the run
_summary.uniqueListingsUnique listing IDs seen
_summary.detailEnrichmentWhether per-item detail calls ran
_summary.isPayingUserWhether the run had a paid account
_summary.endpointEndpoints used
_summary.finishedAtRun finish time

The two flags that change your analysis

  • enrichWithDetails: false means condition, sellerType, views, favorites, conversations, hasWarranty and bump will be null. These fields come from the per-item detail endpoint, not the search payload. The run summary's detailEnrichment field tells you which mode produced the data — check it before you trust those columns.
  • isReserved is filtered out by default. If you need reserved listings (to measure demand rather than availability), set includeReserved: true.

Example output

{
"id": "123456789",
"title": "iPhone 14 Pro 256GB estado perfecto con caja",
"description": "Vendido con caja y cable. Bateria al 100%. Sin marcas de uso.",
"url": "https://wallapop.com/item/123456789/iphone-14-pro-256gb",
"listingUrl": "https://wallapop.com/item/123456789/iphone-14-pro-256gb",
"price": 749.0,
"currency": "EUR",
"condition": "Como nuevo",
"conditionValue": "as_good_as_new",
"isRefurbished": false,
"hasWarranty": false,
"category": "Móviles y Telefonía",
"categoryPath": ["Electrónica", "Móviles y Telefonía", "Smartphones"],
"categoryId": "12403",
"itemType": "MOBILE_PHONE",
"photos": ["https://pre-cdn.wallapop.com/123456789/1.jpg"],
"photoCount": 4,
"sellerId": "u-987654",
"sellerType": "private",
"sellerLocation": {
"city": "Barcelona",
"region": "Cataluña",
"country": "ES",
"postalCode": "08012",
"latitude": 41.3874,
"longitude": 2.1686
},
"bump": null,
"postedAt": "2026-09-28T09:12:00.000Z",
"postedAtMs": 1790590320000,
"updatedAt": "2026-09-28T09:12:00.000Z",
"ageDays": 2,
"shipping": true,
"itemIsShippable": true,
"supportsShipping": true,
"isReserved": false,
"views": 412,
"favorites": 27,
"conversations": 5,
"characteristics": "128GB, 6.1 pulgadas, iOS 18",
"characteristicsDetails": [
{ "attribute": "Capacidad", "value": "256 GB" },
{ "attribute": "Color", "value": "Morado oscuro" }
],
"query": "iphone 14",
"country": "ES",
"scrapedAt": "2026-09-30T11:40:08.000Z"
}

Run summary row:

{
"_summary": {
"totalListings": 200,
"uniqueListings": 198,
"isPayingUser": true,
"detailEnrichment": true,
"endpoint": "https://api.wallapop.com/api/v3/search + https://api.wallapop.com/api/v3/items/{id}",
"finishedAt": "2026-09-30T11:41:52.000Z"
}
}

Monitor secondhand prices on a schedule

Secondhand prices move fast and listings disappear quickly. Recurring runs are how you keep up:

  • Daily — same keyword and city; diff price to catch drops and new bargain stock
  • Weekly — same coordinates; diff id against the previous run to find newly listed items
  • Monthly — whole-country sweeps with orderBy: newest to measure market depth
  • Cross-border arbitrage watch — run the same keyword in ES, PT and IT each week and diff price for the same categoryId
  • Engagement benchmarks — views, favorites and ageDays together give you a listings-quality benchmark by category
  • Wire into your stack — Apify webhooks, Zapier, Make, Google Sheets and 100+ integrations fire on run completion; the dataset exports as JSON, CSV, Excel, XML, HTML or RSS

Keep enrichWithDetails: true on the daily run if you care about condition and engagement; drop it if you only track headline prices.



FAQ

Why do other Wallapop scrapers return nothing?

Almost always the same reason: they do not send the mandatory X-Platform: web header. Wallapop's api.wallapop.com/api/v3 responds 403 to requests without it. It is one header, and it is the whole difference between a working scraper and an empty dataset.

Why are my results all from one city?

Because Wallapop is geo-targeted and country only sets a default coordinate — Madrid for ES, Lisbon for PT, Rome for IT. To target Barcelona you must pass latitude: 41.3874 and longitude: 2.1686 explicitly. The country field alone is never a city filter.

Why is condition in Spanish when I searched in English?

Because condition is the localized label — Como nuevo, Buen estado, Correcto. That is what a local buyer sees, so it is the right field for display. For analysis across ES, PT and IT, group on conditionValue instead: it is a stable machine slug that does not change with the front-end language.

Why is condition null?

You set enrichWithDetails: false. The search payload does not carry condition — it only comes from the per-item detail endpoint. Turning enrichment off roughly halves your requests but costs you condition, conditionValue, sellerType, views, favorites, conversations, hasWarranty and bump. Check _summary.detailEnrichment to see which mode produced a dataset.

Is maxItems really unlimited?

Not on a free account. maxItems is capped at 1000, but free-plan users are limited to 10 listings per run regardless of what they set. The run summary's _summary.isPayingUser records which tier ran. Raise maxItems on a paid plan.

Can I include reserved listings?

Yes, set includeReserved: true. By default they are skipped, because a reserved listing is no longer buyable. If you are measuring demand rather than available stock, including reserved is the correct choice.

Does it need a browser or a proxy?

No. It is API-only against Wallapop's own JSON endpoints, with the required headers, a session pool and 3 parallel requests. No headless browser, no CAPTCHA solving, no residential proxy needed. Default run uses no proxy at 256 MB.

Can I scrape a specific listing without searching?

Yes — pass the /item/<id>/<slug> URL in startUrls. It is resolved detail-only, skipping the search pagination entirely. This is also the cheapest way to refresh a roster of listings you already track.

Why does the dataset include a _summary row?

It is a run-level record, not a listing: totals, unique listing count, whether detail enrichment ran, the account tier and the endpoints used. It is convenient for logging a monitoring run and it is flagged with the _ prefix so it is trivially filterable out of analysis. Exclude rows where _summary exists when you build a listing-level dataset.


For AI Agents & LLM Apps

Callable via the Apify MCP server and the Apify API. Returns one dataset — one row per listing — plus a _summary run-record row.

Minimal valid input — one keyword, default ES coordinates, search payload only:

{ "keywords": ["iphone 14"] }

Full detailed run targeted at a specific city:

{
"keywords": ["iphone 14"],
"country": "ES",
"latitude": 41.3874,
"longitude": 2.1686,
"enrichWithDetails": true,
"maxItems": 200
}

Output field list — id, title, description, url, listingUrl, shareUrl, price, currency, condition, conditionValue, isRefurbished, hasWarranty, category, categoryPath, categoryId, itemType, photos, photoCount, sellerId, sellerType, sellerLocation, bump, postedAt, postedAtMs, updatedAt, ageDays, shipping, itemIsShippable, supportsShipping, isReserved, views, favorites, conversations, characteristics, characteristicsDetails, query, country, scrapedAt.

Behaviors an agent should know

  • country only sets a default coordinate (ES→Madrid, PT→Lisbon, IT→Rome). To target a city you must pass latitude and longitude. Omitting them returns results around the capital.
  • enrichWithDetails defaults to true. Setting it to false halves the requests but nulls condition, conditionValue, sellerType, views, favorites, conversations, hasWarranty, bump, shareUrl and characteristics. Read _summary.detailEnrichment before using those fields.
  • Free-plan users are capped at 10 listings per run, regardless of maxItems (maxItems itself caps at 1000). _summary.isPayingUser records the tier.
  • One billing event per dataset row (apify-default-dataset-item), so the _summary row is billed like any other row. If you need to strip it for analysis, filter WHERE _summary IS NULL.
  • startUrls and keywords both accepted. /search?keywords= URLs are converted into API search requests; /item/<id>/<slug> URLs are detail-only and skip pagination. Providing both runs both.
  • Reserved listings are excluded by default (includeReserved: false).
  • conditionValue is the analysis-safe field, not condition, which is localized per front end.
  • Deduplicate on id across keywords and start URLs — uniqueListings in _summary tells you how much overlap a run had.
  • Prices are EUR across all three marketplaces; currency comes from the API rather than being assumed.

Billing model — pay per event: result ($0.0008–$0.001 per dataset row) plus a per-run Actor Start event scaled by memory. Free-plan users are limited to 10 rows per run.


This Actor is an independent third-party tool. It is not affiliated with, endorsed by, sponsored by, or connected with Wallapop, S.L.U. or its parent group.

It reads only publicly accessible data — the JSON endpoints that power Wallapop's own public website, and publicly visible listing pages. It does not log in, does not create an account, does not use the official Wallapop business API or any partner token, does not solve CAPTCHAs, and does not use proxies by default. It reads the same public search endpoint a logged-out browser visitor uses.

Output includes seller identity data — seller account IDs, and city, region, postal code and coordinates of the seller's location. This is personal data about individuals where sellers are private individuals. You are responsible for your own lawful basis for processing it, for complying with the EU/UK GDPR and applicable national data protection law, and for honouring deletion requests.

Wallapop's terms of use prohibit automated scraping and scraping circumvention, and prohibit using scraped data to build competing directories or for unsolicited contact of sellers. Review their terms carefully before any collection, and do not use this data to contact sellers in breach of applicable marketing law (including GDPR/ePrivacy and, where applicable, LSSI-equivalent rules in Spain, Portugal and Italy). Commercial or high-volume extraction should go through Wallapop's official business or data partnerships.

This Actor is a data-collection tool; it does not provide legal advice and makes no claim that any particular use is permitted.


SEO Keywords

wallapop scraper, wallapop api, secondhand marketplace data, wallapop spain, wallapop portugal, wallapop italy, resale price tracking, used iphone prices, wallapop alternatives, marketplace scraping spain, product condition data, seller type analysis, resale arbitrage research, classified ads data, second hand market research, wallapop listings, cheap scraper wallapop, spanish ecommerce data, european marketplace data, buying and selling app data, market entry analysis spain, price monitoring tools, wallapop export, mercadona wallapop, wallapop search api