Autoplius.lt Car Ads Extractor avatar

Autoplius.lt Car Ads Extractor

Under maintenance

Pricing

Pay per usage

Go to Apify Store
Autoplius.lt Car Ads Extractor

Autoplius.lt Car Ads Extractor

Under maintenance

Extracts publicly available used-car listings from Autoplius.lt. Paste a search URL from the site and every matching public ad comes back as structured data — price, year, mileage, VIN, photos and the full parameter table. Only data any visitor can see on the site is returned.

Pricing

Pay per usage

Rating

0.0

(0)

Developer

steeriq

steeriq

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

2

Monthly active users

11 days ago

Last modified

Share

What does Autoplius.lt Car Ads Extractor do?

This actor turns the used-car listings on Autoplius.lt — Lithuania's largest car marketplace — into structured data: price, year, mileage, engine, gearbox, VIN, photos and the full parameter table for every ad a search matches. Paste a search URL from the site, run the actor, and get a dataset back — no code required, though the same input works identically through the API for a scheduled or programmatic pipeline.

Everything it collects is what any visitor sees on Autoplius' own public pages. It signs in to nothing and reaches nothing behind a login, a paywall or a private seller area.

Built on Crawlee and the Apify SDK, it gets Apify's proxy rotation, scheduling, dataset export and monitoring for free — you don't manage a server, a proxy pool, or a Chromium install.

Why use this actor?

  • Market research and pricing. Pull every ad for a make/model/year band to see what cars are actually asking and selling for right now, not last quarter.
  • Lead generation for dealers. Watch a segment (e.g. diesel estates under €15k) for new listings without refreshing the site by hand.
  • Fleet or inventory monitoring. Track your own listings' visibility, or a competitor's, over time.
  • Data feeds. Cars, prices and specs as clean JSON/CSV for a downstream app, spreadsheet, or BI tool.

How to use Autoplius.lt Car Ads Extractor

  1. Open autoplius.lt and build the search you want using the site's own filters — make, model, price, year, equipment, seller type, damage status, colour, anything the site offers.
  2. Copy the resulting URL and paste it into Start URLs on the Input tab.
  3. Click Start. Leave the other fields on their defaults for a first run.
  4. When the run finishes, open the Output tab, or download the dataset as JSON, CSV, Excel or HTML from the Export button.

Several Start URLs are fine — their results are merged and de-duplicated, so two overlapping searches never produce the same ad twice.

{
"startUrls": [
{
"url": "https://en.autoplius.lt/ads/used-cars?category_id=2&make_id[97]=&make_id_list=97",
},
],
"scrapeDetails": true,
"maxItems": 1000,
}

Both autoplius.lt and en.autoplius.lt URLs work — a Lithuanian or Russian or Latvian search URL is rewritten onto the English site before it's fetched, so field labels and values always come back in English regardless of which language you searched in.

Single ad URLs work too

Start URLs don't have to be searches. Paste a link straight to one ad — copied off the site, or out of another dataset — and the actor recognizes it and scrapes just that ad directly, skipping the search/listing step entirely. Anything else in Start URLs is treated as a search and paginated as usual. The two are told apart automatically, by whether the URL carries an ad id (the -<digits>.html at the end), so a mix of search and single-ad URLs in the same run works with nothing to configure.

The filter fields are a fallback

makes, priceFrom/priceTo, yearFrom/yearTo, mileageFrom/mileageTo, powerFrom/powerTo, fuelType, bodyType and gearbox exist for callers building input programmatically who don't have a URL to hand. They rebuild an Autoplius search from scratch and reach only a subset of what the site's own search can express — anything else the site offers (only cars in Lithuania, exclude a given country, equipment, colour, seller type, damage status) is reachable only by pasting a URL.

They're used only when Start URLs is empty — set a Start URL and every filter field is silently ignored (the run log names each one it dropped, so nothing fails quietly). Two limits worth knowing if you rely on them: make names must match the built-in list exactly, and model IDs are site-internal numbers you still have to copy out of a URL — at which point pasting the whole URL is simpler.

Input

FieldTypeDescription
startUrlsarrayPrimary input. One or more autoplius.lt search URLs.
makes, yearFrom/To, priceFrom/To, mileageFrom/To, powerFrom/To, fuelType, bodyType, gearboxFallback filters, used only when startUrls is empty.
scrapeDetailsbooleanVisit each ad's own page for the full parameter set, VIN, description and every photo. Off = results-page fields only, at a fraction of the requests. Default true.
transportstringauto (HTTP, capped browser fallback for blocked requests — recommended), http (cheapest, no fallback), or browser (renders every page in Chromium). Default auto.
maxItemsintegerStop after this many ads. Default 1000.
maxConcurrencyintegerParallel requests for the HTTP tier. Default 5.
maxRequestRetriesintegerRetries before a blocked request is handed to the browser fallback (auto mode). Default 5.
proxyConfigurationobjectDefaults to Apify's residential proxy pinned to Lithuania — see below.
skipSeenAdsbooleanAdvanced. Skip ads a previous run with this actor already pushed. Default false.
seenAdsStoreNamestringNames the store skipSeenAds remembers ad ids in. Default AUTOPLIUS-SEEN-ADS.

See the Input tab for the full schema, including the make list.

A Lithuania-pinned residential proxy is not optional. Autoplius sits behind Cloudflare and 403s most foreign and datacenter exit IPs — testing an unpinned proxy got blocked on every attempt, while an LT-pinned residential proxy got through. The default is already correct; changing it is what breaks runs.

Output

One dataset record per ad. Known parameters are mapped to typed fields, and every label/value row from the ad's own parameter table is additionally kept verbatim in rawParameters — so a label the site adds or renames shows up as a new key instead of silently vanishing.

{
"id": "31732033",
"url": "https://en.autoplius.lt/ads/bmw-328-2-0-l-saloon-sedan-2012-petrol-31732033.html",
"title": "BMW 328",
"make": "BMW",
"model": "328",
"price": 25000,
"currency": "EUR",
"year": 2012,
"mileageKm": 282000,
"fuelType": "Petrol",
"gearbox": "Automatic",
"bodyType": "Saloon / sedan",
"engineCapacityL": 2,
"powerKw": 180,
"vin": null,
"co2Gkm": 149,
"location": "Kėdainiai, Lithuania",
"imageUrls": [
"https://autoplius-img.dgn.lt/ann_3_407330359/bmw-328-2-0-l-saloon-sedan-2012-petrol-0.jpg"
],
"isSold": false,
"rawParameters": { "Climate control": "Climate control", "Advertisement ID": "A31732033" },
"scrapedAt": "2026-09-03T18:40:34.746Z"
}

You can download the dataset in JSON, CSV, Excel, HTML, XML or RSS from the Export button on the Output tab, or pull it through the Apify API for automation.

Data fields

FieldDescription
id, urlAd id and canonical URL.
title, make, modelListing title, split into make/model.
price, currencyAsking price.
year, firstRegistrationFirst-registration year and the raw date string.
mileageKmOdometer reading.
fuelType, gearbox, bodyTypeAs shown on the ad.
engineCapacityL, powerKwEngine size and power.
drivenWheels, doors, color, seats, wheelDiameter(detail pages only)
vin(detail pages only) Null unless the seller's VIN passes a plausibility check — Autoplius masks most VINs behind a click-to-reveal the actor doesn't interact with.
co2Gkm, euroStandard, technicalInspectionUntil, weightKg, registrationTaxEur(detail pages only)
locationSeller's stated location.
description(detail pages only) Free-text ad description.
imageUrlsThis ad's own photos — the related-ads carousel elsewhere on the page is deliberately excluded.
isSoldWhether the ad is flagged sold/inactive.
rawParameters(detail pages only) Every label/value row from the ad, verbatim — the safety net for anything not mapped above.
scrapedAtISO timestamp of extraction.

Consistency with the sibling Autogidas actor

This actor has a sibling, the Autogidas.lt Car Ads Extractor, covering a second Lithuanian car marketplace. Every field the two sites both publish uses the same name and type in both actors' output, so a pipeline consuming either dataset can treat them interchangeably for the fields they share. A few fields deliberately differ, because the sites themselves differ:

  • vin here is null unless the value looks like a genuine, unmasked VIN. The sibling actor's vinPartial is always just the visible (usually masked) prefix text, unvalidated — a different kind of value, not the same field under two names.
  • powerFrom/powerTo (input) exist here because Autoplius' search exposes a power filter; the sibling site doesn't, so it has no equivalent.
  • The sibling actor additionally reports sellerName, cylinders, gears, firstRegistrationCountry, steeringSide, defects and per-context fuel consumption, because Autogidas' parameter table publishes them and Autoplius' doesn't.

These field names and shapes are meant to stay stable — a schema change here should be considered alongside the sibling actor's, not made independently.

Run outcome

Alongside the dataset, every run writes a RUN-SUMMARY record to its default key-value store and puts the same headline into the run's status message. It tells a downstream actor whether the dataset it just received is the whole answer, without having to guess from the item count:

outcomeRun statusMeans
completeSUCCEEDEDEvery ad the search offered was extracted.
partialSUCCEEDEDReal data came back, but some pages never did — dataset incomplete.
emptySUCCEEDEDEvery page loaded fine and the search matched no ads.
blockedFAILEDNothing could be read at all — usually proxies or a JS challenge.
{
"outcome": "partial",
"adsPushed": 20,
"adsExpected": 25,
"adsMissing": 5,
"failedListPages": 1,
"failedDetailPages": 4,
"skippedKnownAds": 0,
"failedUrls": [
{
"url": "https://autoplius.lt/skelbimai/naudoti-automobiliai/audi-a6-12345678.html",
"label": "DETAIL",
"message": "Blocked (403)"
}
],
"failedUrlsTruncated": false
}

adsExpected is how many ads the search pages offered and the run committed to, so adsMissing is the real shortfall. A failed DETAIL page costs one known ad; a failed LIST page costs a whole page of ads the run never learned about, which is why the two are counted separately. failedUrls is capped at 100 entries, with failedUrlsTruncated flagging the cut — retry them by feeding them back in as startUrls.

Reading it from a calling actor:

const run = await client.actor('you/autoplius-scraper').call(input);
const { value: summary } = await client
.keyValueStore(run.defaultKeyValueStoreId)
.getRecord('RUN-SUMMARY');
if (summary.outcome === 'partial') {
console.warn(`Incomplete: ${summary.adsMissing} ad(s) missing`, summary.failedUrls);
}

run.statusMessage carries the same headline as plain text if you only need a cheap check and not the failed urls.

Pricing / cost estimation

This actor bills on Apify's standard pay-per-usage compute-unit model — there's no separate per-result charge. Two things drive cost, both under your control on the Input tab:

  • scrapeDetails. Results-page-only runs are cheap: one request per 20 ads. Full details cost one extra request per ad — turn it off if you only need price/year/mileage/location.
  • transport. Left on auto (the default), almost every request is a plain HTTP fetch; Chromium is only launched for the small number Cloudflare actually blocks, and even then at capped concurrency. Forcing transport="browser" prices every single request at browser rates.

A typical scrapeDetails: true, maxItems: 1000 run on the default 1024 MB should stay well under the Apify Free plan's monthly compute-unit allowance — check the Runs tab for exact figures after your first run, since actual cost depends on how many requests needed the browser fallback.

Tips for optimizing runs

  • Slice large pulls instead of raising maxItems past ~5,500. One search caps out around 275 pages; past that the site re-serves the last page instead of an empty one. To cover more of the ~40k-ad catalogue, pass several Start URLs sliced by make, price band or year instead.
  • Turn skipSeenAds on for a recurring/scheduled search. It remembers every ad id already pushed in a store that survives across runs, so a daily "what's new" run only pays for genuinely new listings. Tradeoff: an ad already seen is never revisited, so a price change or a sold flag on an old ad won't be picked up — run occasionally with it off for a full refresh.
  • Leave transport on auto. It's never more expensive than http when nothing gets blocked, and it recovers automatically when something does.
  • Don't lower maxConcurrency or raise it past ~10 without a reason — Cloudflare's challenge rate is sensitive to burstiness, and a blocked run costs more (retries, browser fallback) than a slightly slower one.

FAQ

Is this legal? The actor only reads pages any visitor can load without logging in. You're responsible for how you use the extracted data — check Autoplius' terms of service and applicable law (e.g. GDPR if a description or seller name ever includes personal data) for your use case.

Why is vin usually null? Autoplius masks most VINs behind a click-to-reveal control on the ad page; the actor doesn't click it, so a masked value is deliberately reported as null rather than the truncated placeholder text underneath it.

A run returned 0 ads. The run status tells you which of the two cases it was. A succeeded run with 0 ads means every page loaded fine and the search genuinely matched nothing — widen the filters, or open the start url in a browser to confirm. A failed run with 0 ads means no page could be read: almost always a proxy problem, so confirm proxyConfiguration is still the LT-pinned residential default (see above). If it's already correct and the site is failing a JS challenge, set transport="browser" to render pages in a real browser, which clears it. A succeeded run can still warn that some requests failed after retries — the dataset is then real but incomplete, and the failed urls are logged as errors.

Found a bug or need a custom field? Open an issue on the actor's Issues tab in Apify Console, or reach out about a custom build for your exact use case.