TypeScript client for Car-Part.com — the largest recycled/used auto parts marketplace in the US with 200M+ parts from thousands of auto recyclers.
- Search by VIN (SmartVin auto-selects the right variant) or Year/Make/Model
- Transparent interchange handling (1-step or 2-step flow)
- 707 part types with common-name aliases
- Full TypeScript types
- Zero runtime dependencies
- ESM + CommonJS
npm install car-part-apiimport { CarPartClient } from 'car-part-api';
const client = new CarPartClient({ zip: '32073' });
const results = await client.search({
vin: '2C3CDXBG2JH247820',
part: 'Caliper',
});
console.log(`Found ${results.results.length} used calipers`);
for (const r of results.results.slice(0, 5)) {
console.log(` ${r.year} ${r.model} — ${r.grade} grade — $${r.price} — ${r.distanceMiles} mi`);
}| Option | Type | Default | Description |
|---|---|---|---|
zip |
string |
required | ZIP code for distance calculations |
location |
string |
'All States' |
Region filter (see LOCATIONS) |
sort |
SortOption |
'price' |
Sort order: 'price', 'zip', 'grade', 'condition', 'year' |
searchMode |
'int' | 'exact' |
'int' |
'int' = interchange (recommended), 'exact' = exact match only |
requestDelay |
number |
1000 |
Min delay between requests (ms) |
cache |
boolean | InterchangeCache |
false |
Cache interchange data to skip Step 1 on repeat searches |
| Param | Type | Default | Description |
|---|---|---|---|
vin |
string |
— | 17-digit VIN (preferred — enables SmartVin) |
year |
string |
— | Vehicle year (YMME fallback) |
model |
string |
— | Make + model, e.g. 'Dodge Charger' (YMME fallback) |
part |
string |
required | Exact part name (see PART_NAMES) |
location |
string |
client default | Override location filter |
sort |
SortOption |
client default | Override sort order |
page |
number |
1 |
Results page |
interchangeVariant |
number |
auto | 0-based index to select a specific variant |
Returns a SearchResult:
interface SearchResult {
results: PartResult[];
page: number;
partSearched: string;
interchangeVariant: string | null; // Selected variant description
allVariants: InterchangeVariant[]; // All available variants
sessionId: string;
searchMode: 'vin' | 'ymme';
}Each PartResult:
interface PartResult {
year: string; // Donor vehicle year
partName: string; // e.g. 'Brake Caliper, Front Left'
model: string; // e.g. 'Dodge Charger'
description: string; // e.g. 'LH,SXT,3.6,8AT,FRONT'
grade: string; // 'A' (top), 'B', 'C', or '0' (ungraded)
stockNumber: string;
price: number; // USD
priceRaw: string; // Original string, e.g. '$241.25'
priceLabel: PriceLabel; // 'actual' | 'undmg' | 'canadian'
priceCAD?: number; // CAD price (Canadian dealers only)
dealer: DealerInfo;
distanceMiles: number;
imageUrl: string | null;
co2eSavingsKg: number | null;
}Returns the available interchange variants without fetching results. Useful for presenting variant choices to users.
const variants = await client.getInterchangeVariants({
vin: '2C3CDXBG2JH247820',
part: 'Caliper',
});
// [
// { description: 'front, 1 piston (opt BR3), LH', selected: true, ... },
// { description: 'front, 1 piston (opt BR3), RH', selected: false, ... },
// ...
// ]One-shot search without creating a client instance:
import { searchParts } from 'car-part-api';
const results = await searchParts({
vin: '2C3CDXBG2JH247820',
part: 'Engine Computer',
zip: '32073',
});Resolves informal part names to exact Car-Part.com values:
import { resolvePartName } from 'car-part-api';
resolvePartName('ecm'); // 'Engine Computer'
resolvePartName('brake caliper'); // 'Caliper'
resolvePartName('headlight'); // 'Headlight Assembly'
resolvePartName('Alternator'); // 'Alternator' (exact match)import { PART_NAMES, LOCATIONS, SORT_OPTIONS, PART_ALIASES } from 'car-part-api';
PART_NAMES; // All 707 valid part names
LOCATIONS; // All 96 location filter values
SORT_OPTIONS; // ['price', 'zip', 'grade', 'condition', 'year']
PART_ALIASES; // Common name -> exact name mappingconst results = await client.search({
year: '2018',
model: 'Dodge Charger',
part: 'Headlight Assembly',
});// First, see what's available
const variants = await client.getInterchangeVariants({
vin: '2C3CDXBG2JH247820',
part: 'Caliper',
});
console.log(variants.map(v => v.description));
// ['front, 1 piston (opt BR3), LH', 'front, 1 piston (opt BR3), RH', ...]
// Then search with a specific variant
const results = await client.search({
vin: '2C3CDXBG2JH247820',
part: 'Caliper',
interchangeVariant: 1, // RH caliper
});const results = await client.search({
vin: '2C3CDXBG2JH247820',
part: 'Alternator',
sort: 'zip',
});const client = new CarPartClient({
zip: '32073',
cache: true, // In-memory cache
});
// First search: 2 requests (interchange + results)
await client.search({ vin: '...', part: 'Caliper' });
// Second search for same part+vehicle: 1 request (cached interchange)
await client.search({ vin: '...', part: 'Caliper', page: 2 });import type { InterchangeCache } from 'car-part-api';
const redisCache: InterchangeCache = {
async get(key) {
const data = await redis.get(`carpart:${key}`);
return data ? JSON.parse(data) : undefined;
},
async set(key, value) {
await redis.set(`carpart:${key}`, JSON.stringify(value), 'EX', 3600);
},
};
const client = new CarPartClient({ zip: '32073', cache: redisCache });Car-Part.com uses a CGI endpoint that returns HTML (not JSON). This library handles the full flow:
- POST with VIN/YMME + part name
- Detect response type — single variant returns results directly; multiple variants return an interchange selection page
- If interchange: parse hidden fields + radio buttons, select the correct variant (SmartVin auto-selects for VIN searches), POST again
- Parse the results HTML table into typed objects
No authentication required. No API key needed.
For advanced use cases, the HTML parsers are exported directly:
import { detectResponseType, parseInterchangePage, parseResultsPage } from 'car-part-api';
const type = detectResponseType(html); // 'results' | 'interchange' | 'error'
const fields = parseInterchangePage(html); // InterchangeFields
const { results } = parseResultsPage(html); // PartResult[]MIT