# carsensor.net Used-Car Resale Value Scout (`woolen_snake/carsensor-resale-value-scout`) Actor

Search carsensor.net used-car listings by freeword and get each one scored against carsensor's own official market-price data.

- **URL**: https://apify.com/woolen\_snake/carsensor-resale-value-scout.md
- **Developed by:** [coco zizi](https://apify.com/woolen_snake) (community)
- **Categories:** E-commerce, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.00005 / actor start

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## carsensor.net Used-Car Resale Value Scout

Searches [carsensor.net](https://www.carsensor.net) (Recruit) used-car listings by **freeword** and returns
each listing with full spec/price/dealer data, plus a **bargain-rate score** computed against carsensor's
own official market-price matrix for that exact maker/model/year. Pay-per-event pricing.

### Features

- Search carsensor.net used-car listings by freeword
- Get price, year, mileage, and repair history per listing
- Score listings against carsensor's own market-price data
- Find undervalued used cars with a bargain-rate score
- Get dealer contact info and vehicle spec details

### ⚠️ Disclaimer (please read)

- This Actor automatically retrieves information that is publicly available on carsensor.net. **You are
  responsible for how you retrieve and use this data.**
- **The site owner's Terms of Use, robots.txt, or access blocking could change without notice, which
  could stop this Actor from working or change its output unexpectedly.**
- **`valueScore` is a heuristic estimate, not a guarantee.** It compares a listing's price to a
  count-weighted average derived from carsensor's own aggregate market-price matrix for that
  maker/model/year (grade-level, not exact-trim-level — see "Valuation logic" below). It does not account
  for individual vehicle condition, equipment differences, or actual negotiated sale prices. **Always
  verify the actual vehicle before making a purchase or resale decision.**

#### Facts confirmed during pre-build research (as of August 10, 2026)

- **Terms of Use**: carsensor.net's general Terms of Use (「カーセンサー.net」ご利用規約) do **not** contain a
  site-wide "no commercial use" clause for the website itself — the one commercial-use restriction in the
  ToS (Article 6) is explicitly scoped to the smartphone app product only. **However**, a separate
  "リクルートWEBサービス利用規約" governs Recruit's **official carsensor.net Web API** (opt-in, requires
  account/API-key registration) and explicitly prohibits monetizing data obtained through that official
  API. This Actor does **not** use that official API — it scrapes the public HTML site — so that
  restriction does not apply to it, but it's worth knowing it exists if you ever consider the official API
  route instead.
- **robots.txt**: `User-agent: *`, no `Crawl-delay`. Disallows are almost entirely user-action/internal
  endpoints (`/usedcar/search.php`, `mylist`, `favorite_*`, `inquiry*`, etc.) — not the listing/detail
  pages this Actor uses. This Actor deliberately avoids `/usedcar/search.php` and instead reaches listings
  via `/usedcar/freeword/` search, which is not disallowed.
- **CDN / bot protection**: Plain `curl` requests (including a bare `curl/8.0` User-Agent, no browser
  emulation) to the top page and to `/usedcar/search.php` returned normal HTTP 200 with `Server: Apache`
  and no Cloudflare-style markers (no `cf-ray`, no JS challenge). Only verified with single, low-frequency
  requests — sustained high-volume behavior has not been tested.

### Privacy / PII design

The dealer contact info shown on a listing page (shop name, address, phone number) is carsensor's own
labeled **business-level public information** — the phone number is a `0078-`-prefixed call-tracking
number tied to the listing, not a dealer employee's personal line. This is analogous to how our PR TIMES
Actor treats a company's own labeled "Company Overview" block, and is not treated as personal contact
information needing redaction.

That said, two fields are free text written by the dealer and could, in principle, contain personal
contact info (e.g. "ご質問は担当◯◯まで" written directly into a listing's remarks) — and a small
sole-proprietor shop's registered name can occasionally be an individual's name rather than a company
name. This Actor applies a safety net (`src/privacyFilter.js`) to exactly those fields right before
output:

- `title` (listing title)
- `description` (the dealer's free-text remark field)
- `seller.name` (dealer/shop name — fallback only, in case of a sole-proprietor shop)

Each is scanned for email-address / phone-number-like regex patterns and person/contact labels (e.g.
"担当:"); any match nulls out that field, and the detection is recorded in the output's
`personalInfoRedactions` field. **`seller.phone` / `seller.address` / `seller.url` are intentionally
excluded from this safety net**, since they are carsensor's own labeled business contact info for the
dealer, not an individual's direct line.

No listing with an actual personal-info match was found during pre-build spot checks (see the sample
output below — `personalInfoRedactions: []`), but this is a safety net for cases the spot check didn't
happen to cover, not a guarantee that the underlying pages never contain such text.

### What does this Actor do?

- Searches carsensor.net's freeword search (`/usedcar/freeword/{keyword}/`) — the same as typing a term
  into the site's search box — and fetches each candidate listing's detail page.
- For each listing, extracts:
  - Price (`車両本体価格` / `支払総額`), correctly handling the **"応談" (price on request) sentinel** —
    when a listing has no fixed price, `price.isNegotiable` is `true` and both price fields are `null`
    instead of the raw placeholder value (`999,999,999`) carsensor uses internally.
  - Year (with Japanese era), mileage, repair/accident history (修復歴), and a spec block (body type,
    transmission, displacement, color, doors, seating, drivetrain, warranty, inspection status, one-owner,
    non-smoking).
  - Maker/model (with carsensor's internal codes, from the page's breadcrumb structured data) and dealer
    contact info.
- Looks up carsensor's own **市場価格(相場)マトリクス** for that maker+model (its `/usedcar/souba/` page)
  and computes a **`valueScore`**: how this listing's price compares to the market-price baseline for its
  specific model year.
- Turning on `onlyWithValueScore` limits output and billing to listings where a score was actually
  computed.

### Who is this for?

Rather than a raw scrape of listing fields, this Actor's differentiation is turning carsensor's own
publicly-available market-price matrix into an immediately usable **bargain-rate number per listing** —
structured output an AI agent or a human resale-flipping decision-maker can act on directly, without
having to separately open and cross-reference the 相場 page themselves (same stack as our BOOTH, SUUMO,
and PR TIMES Actors: JavaScript ESM, Apify SDK, Pay-per-event pricing).

Two things worth being upfront about, decided during pre-build research (see project notes):

- **This is not pitched on "exclusive data."** carsensor has no per-vehicle third-party inspection/
  appraisal data (no AIS/JAAA-style report), and both its 修復歴 (repair history) field and its
  price×year/mileage market matrix have close equivalents on goo-net and other major Japanese used-car
  sites. The value here is turning data that already exists into a ready-to-use score, not surfacing data
  nobody else has.
- **No cross-checking against goo-net or other sources in this version.** Combining carsensor with a
  goo-net-style source (for inventory overlap / price cross-validation) was considered as a differentiator
  but intentionally left out of v0.1 to keep scope manageable — see "Possible future extensions" below.

### Input

| Parameter | Type | Default | Description |
|---|---|---|---|
| `freeword` | string | *(required)* | Search term, same as carsensor's own search box (e.g. `"プリウス"`, a maker name, or a maker+model combo) |
| `onlyWithValueScore` | boolean | `false` | When on, only outputs and charges for listings where a value score was computed |
| `maxItems` | integer | `20` | Cap on the number of listings output/charged (max 200) |
| `maxDetailFetches` | integer | `60` | Safety cap on how many detail pages are actually fetched from the search results (max 300) |
| `maxSearchPages` | integer | `5` | Safety cap on how many freeword search result pages are crawled to collect candidate URLs (max 20) |
| `requestDelayMs` | integer | `1500` | Delay between requests in ms. Cannot be set below 1000ms for safety |

### Output

The following is actual output from a real run of this Actor against the live site (August 12, 2026,
freeword "プリウス") — regenerated after the market-matrix parsing fix described under "Pricing" below, so
these numbers reflect the corrected valuation logic.

```json
{
  "sourceUrl": "https://www.carsensor.net/usedcar/detail/AU7231736290/index.html",
  "bkkn": "AU7231736290",
  "title": "トヨタ プリウスα G 5ニンノリ　バックカメラ ドラレコ前後 クルコン",
  "maker": { "code": "TO", "name": "トヨタ" },
  "model": { "code": "220", "name": "プリウスα" },
  "price": { "basePriceYen": 1100000, "totalPriceYen": 1223000, "isNegotiable": false },
  "year": 2016,
  "yearEra": "H28",
  "mileageManKm": 5.4,
  "repairHistory": "なし",
  "spec": {
    "bodyType": "ミニバン",
    "transmission": "その他AT",
    "displacement": "1800cc",
    "color": "パールマイカ",
    "doorCount": "5",
    "seatingCapacity": "5名",
    "driveType": "2WD",
    "warranty": "付き / 1年 / 距離無制限",
    "inspectionStatus": "車検整備付",
    "legalMaintenance": "付き",
    "oneOwner": "－",
    "nonSmokingCar": "－"
  },
  "region": "大阪府/大阪北部",
  "seller": {
    "name": "ネッツトヨタニューリー北大阪（株） 千里店",
    "url": "https://www.carsensor.net/shop/osaka/100644015/",
    "address": "大阪府吹田市山田西１－３６－１０",
    "phone": "0078-6002-061253",
    "businessHours": "10:00～18:00"
  },
  "description": "当店は駐車場完備！お気軽にマイカーでお越しくださいませ。ご購入後の走行距離は無制限。全ての中古車に1年間の無償保証がついています。",
  "image": "https://ccsrpcma.carsensor.net/CSphoto/bkkn/750/408/UT0053750408/UT0053750408_002L.JPG",
  "marketBaseline": {
    "soubaUrl": "https://www.carsensor.net/usedcar/souba/TO_S220/",
    "sampleSize": 78,
    "estimatedMarketPriceYen": 1384615,
    "method": "souba-price-x-year-matrix-weighted-average"
  },
  "valueScore": { "bargainRatePercent": 20.6, "verdict": "割安", "confidence": "normal" },
  "disclaimer": "carsensor.net上の公開情報を基に自動生成した参考データです。...",
  "scrapedAt": "2026-08-12T00:00:00.000Z",
  "personalInfoRedactions": []
}
```

An example of the **negotiable-price case** (verified against a real "応談" listing,
`AU5867522762`): `price` comes back as `{ "basePriceYen": null, "totalPriceYen": null, "isNegotiable":
true }` instead of carsensor's raw internal placeholder (`999,999,999`), and `valueScore` is `null` since
there's no price to score.

### Valuation logic

1. **Maker/model resolution** (`src/carsensorClient.js`): a detail page's breadcrumb structured data
   (`BreadcrumbList` JSON-LD) contains an entry for the model-level page in the form
   `/usedcar/b{makerCode}/s{modelCode}/index.html`. This is parsed to get `maker.code`/`model.code`.
2. **Market-price matrix lookup**: carsensor's own 相場(souba) page for that maker+model is at
   `/usedcar/souba/{makerCode}_S{modelCode}/` (verified directly, e.g. `bLE`/`s012` → `souba/LE_S012/`).
   That page embeds three cross-tab matrices (price×year, price×mileage, year×mileage) as links whose
   query string carries the exact bucket boundaries (`PMIN`/`PMAX`/`YMIN`/`YMAX`) and count. This Actor
   uses the **price×year** matrix (identified via the `fed=...pricemodelyear...` marker in each link's
   query string, which is more robust than relying on DOM tab position).
3. **Baseline estimate** (`src/valuation.js`): for the listing's exact model year, all matching price
   buckets are pulled from the matrix and combined into a **count-weighted average price** — this is
   `marketBaseline.estimatedMarketPriceYen`, with `sampleSize` reported alongside it as a transparency/
   confidence signal. Open-ended top/bottom buckets (e.g. "415万円以上") don't have a real upper/lower
   bound, so their midpoint is estimated with a fixed +15%/-15% heuristic adjustment off the known
   boundary — this is a rough approximation, not a statistically derived figure.
4. **Bargain rate**: `(estimatedMarketPriceYen - basePriceYen) / estimatedMarketPriceYen * 100`. Verdict is
   `割安` (undervalued) at +15% or more, `割高` (overvalued) at -15% or less, `相場並み` in between. Fixed
   thresholds, not tuned against any ground truth.
5. **Confidence**: `low` when the matched year's `sampleSize` is under 5 listings (a thin market for that
   year makes the weighted average less trustworthy).

**Known limitation**: the market matrix is at the **grade level** (e.g. all Lexus CT trims combined), not
matched to the listing's specific trim/equipment — so `valueScore` should be read as "vs. this model's
market overall for that year," not "vs. this exact trim." Mileage is not currently factored into the
baseline even though carsensor's souba page also exposes a price×mileage matrix — a future version could
combine both matrices for a tighter estimate (see below).

### Pricing

| Event | Price | Trigger |
|---|---|---|
| Actor Start (`apify-actor-start`) | $0.00005 | Once per run (Apify's standard synthetic event) |
| Listing extracted (`listing-extracted`) | $0.015 | Per listing output, with full spec/price/dealer data |
| Value score computed (`value-score-computed`) | $0.065 | Charged in addition to listing-extracted when a bargain-rate score was successfully computed |

A scored listing costs $0.08 in total; an unscored listing (negotiable price, or no matching market data)
costs $0.015.

#### How the price was set (measured on Apify, August 10, 2026)

This Actor was deployed (`apify push`) and run three times with production-like input (freeword search,
25-30 items each), and Apify's measured real infrastructure cost (`usageTotalUsd`, covering Compute
Units, data transfer, and storage writes) was checked.

| Run | Freeword | Items output | Value scores computed | Duration | Real infra cost | Cost per item |
|---|---|---|---|---|---|---|
| 1 | プリウス | 25 | 25/25 | 49.1s | $0.0029135 | $0.0001165 |
| 2 | プリウス | 25 | 25/25 | 49.9s | $0.0029605 | $0.0001184 |
| 3 | アルファード | 30 | 30/30 | 62.5s | $0.0036906 | $0.0001230 |
| Blended | — | 80 | 80/80 | — | $0.0095646 | $0.0001196 |

About 92-93% of the cost is `ACTOR_COMPUTE_UNITS`; the rest is negligible dataset-write/data-transfer
cost. All three runs happened to compute a value score for every listing (both freewords are common
models with abundant market data), so we don't have a real-world run isolating `listing-extracted`-only
cost — but architecturally, `value-score-computed`'s only marginal infra cost is the souba/market-price
fetch, and that's cached per maker+model for the whole run (typically 2-3 distinct models per 25-30
listings), so its true marginal cost per scored item is a small fraction of the ~$0.00012/item blended
figure above, not something separately measurable at this scale.

**Note on this measurement**: the first run surfaced a real parsing bug in the market-matrix logic
(carsensor's souba page links include row/column "total" cells alongside real per-cell data, which were
initially miscounted and produced a handful of implausible scores). This has been fixed and reverified —
sample sizes now exactly match carsensor's own displayed totals as a sanity check. The pricing below is
based on the two **post-fix** runs (2 and 3); run 1 is included in the cost table only for its infra-cost/
timing data, not its (superseded) computed values.

Following the same approach as our SUUMO Actor (which priced $0.08 against a measured infra cost of about
$0.0004/item, roughly a 200x margin) and our PR TIMES Actor ($0.015 base / +$0.045 signal bonus):

- `listing-extracted` is set to $0.015 — the same tier as PR TIMES's `release-classified`, since both
  represent a comparably rich plain structured record (full spec/price/dealer data here vs. official
  classification + company profile there). Against our measured ~$0.00012/item, that's roughly a
  **125x margin**, well above the 100x floor.
- `value-score-computed` is set to $0.065 (total $0.08 for a scored listing) — anchored to the same total
  figure as our SUUMO Actor's per-record price, on the same reasoning: this is the "one investment/resale
  decision" component, priced on the value of the decision it enables rather than its (near-zero
  incremental) infra cost. A used-car flip's typical margin is smaller than a typical real-estate deal, so
  pricing at parity with (not above) the SUUMO figure felt like the right calibration rather than pricing
  higher just because we could. Against measured cost, the full $0.08 scored-listing price is roughly a
  **667x margin** — comfortably clearing the 100x floor by a wide margin, which is expected since this
  price is value-anchored, not cost-anchored.

**Status**: Pay-per-event pricing is enabled in Apify Console and verified live — a real run showed
`pricingInfo.pricingModel: "PAY_PER_EVENT"`, `chargedEventCounts` matching the run exactly (no missed or
double charges), and no automatic/implicit charge events beyond the three declared above.

### Load management

There's a default **1500ms** delay between every HTTP request this Actor makes (search result pages,
listing detail pages, and souba/market-price pages all share one pacing clock via
`carsensorClient.js`'s `politeGetHtml`). Configurable via `requestDelayMs`, but it cannot be set below
1000ms for safety. Souba/market-price pages are fetched at most once per distinct maker+model per run (the
`soubaCache` Map in `src/main.js`) — a freeword search tends to return many listings of the same model, so
this meaningfully cuts down on repeat requests.

### FAQ

**What if carsensor changes its page layout?**
The selectors and URL patterns in `src/carsensorClient.js` were verified against real carsensor.net
response HTML (freeword search pages, listing detail pages, souba/market-price pages) as of August 10,
2026\. carsensor's markup may change over time; if this stops working, run `npm run test-connectivity` to
inspect the actual response and adjust accordingly.

**Why does a search only return a few pages of results?**
Freeword search covers only `maxSearchPages` pages (default 5) of results per run — there's no "full
sync" mode in this version.

**Why is `valueScore` sometimes missing?**
It can't be computed for listings priced "応談" (negotiable — no fixed price to compare), for
maker/models whose breadcrumb data doesn't resolve to a `b{code}/s{code}` pair, or where the souba page
has no matching data for that model year.

**Does the bargain score account for mileage or exact trim/grade?**
Not currently. The market matrix is grade-level, not trim-level, and mileage isn't factored into the
baseline yet (see "Valuation logic" above).

### Possible future extensions (not implemented in v0.1)

- **Cross-checking against a goo-net-style source**: combining carsensor's listings with another
  aggregator's for inventory overlap detection and independent price cross-validation was considered as a
  differentiator during pre-build research, but intentionally deferred to keep this version's scope
  manageable.
- **Mileage-adjusted baseline**: combining the price×year and price×mileage (and year×mileage) matrices
  for a tighter market-price estimate than the price×year-only baseline used today.
- **Region-adjusted baseline**: carsensor's souba page also supports a regional filter; this Actor doesn't
  currently use it, so the baseline is national, not local to the listing's prefecture.

# Actor input Schema

## `freeword` (type: `string`):

Free-text search term, same as typing into carsensor's search box (e.g. "プリウス", "アルファード", a maker name, or a maker+model combo). Used against carsensor's /usedcar/freeword/ search.

## `onlyWithValueScore` (type: `boolean`):

When enabled, only listings where a bargain-rate score was successfully computed are output and charged (negotiable-price listings, or models with no matching market-price data, are skipped and not charged).

## `maxItems` (type: `integer`):

Maximum number of listings to output. A charge event is generated for every item, so this directly drives run cost.

## `maxDetailFetches` (type: `integer`):

Upper limit on how many listing detail pages are actually fetched from the search results (when onlyWithValueScore is on, this also counts listings skipped without a score and not charged).

## `maxSearchPages` (type: `integer`):

Upper limit on how many pages of the freeword search results are crawled to collect candidate listing URLs.

## `requestDelayMs` (type: `integer`):

Delay between requests to reduce load on the carsensor.net server. Cannot be set below 1000ms for safety.

## Actor input object example

```json
{
  "freeword": "",
  "onlyWithValueScore": false,
  "maxItems": 20,
  "maxDetailFetches": 60,
  "maxSearchPages": 5,
  "requestDelayMs": 1500
}
```

# Actor output Schema

## `scoredListings` (type: `string`):

Used-car listings with full spec/price/dealer data and a bargain-rate score against carsensor's own market-price matrix.

# 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("woolen_snake/carsensor-resale-value-scout").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 = {}

# Run the Actor and wait for it to finish
run = client.actor("woolen_snake/carsensor-resale-value-scout").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call woolen_snake/carsensor-resale-value-scout --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,woolen_snake/carsensor-resale-value-scout"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/IOil3cImRgTqqCY8k/builds/oxPLXwFhqqeoEeDld/openapi.json
