Skip to content

Instantly share code, notes, and snippets.

@AKASGaming
Last active January 18, 2025 22:46
Show Gist options
  • Save AKASGaming/f11c088e54ae4051544da5751485e5b9 to your computer and use it in GitHub Desktop.
Save AKASGaming/f11c088e54ae4051544da5751485e5b9 to your computer and use it in GitHub Desktop.
Exports your car's Service History from the CarFax.com Service History page to CSV
// Paste the following code into Chrome's Developer Tools (Ctrl + Shift + I)
(function () {
const serviceRecords = [];
const serviceRecordElements = document.querySelectorAll('[id^="service-record-"]');
let lastValidOdometer = 0; // Default for missing odometer values
// Iterate through all service records visible on the page
serviceRecordElements.forEach((serviceRecordElement) => {
const dateSelector = '.service-history-header > div.flex-row.flex-wrap > div:nth-child(1) > div';
const odometerSelector = '.service-history-header > div.flex-row.flex-wrap > div:nth-child(2) > div';
const servicesPerformedSelector = '.service-performed ul';
const shopSelector = '.service-history-header__title';
const shopLinkSelector = '.service-history-header__title a';
// Extract data for each record
const dateElement = serviceRecordElement.querySelector(dateSelector);
const odometerElement = serviceRecordElement.querySelector(odometerSelector);
const servicesPerformedElement = serviceRecordElement.querySelector(servicesPerformedSelector);
const shopElement = serviceRecordElement.querySelector(shopSelector);
const shopLinkElement = serviceRecordElement.querySelector(shopLinkSelector);
const dateServiced = dateElement ? dateElement.textContent.trim() : '';
let odometer = odometerElement ? odometerElement.textContent.trim() : '';
odometer = odometer.replace(/[^\d]/g, ''); // Remove all non-numeric characters
// If odometer is empty, use the last valid value
if (!odometer) {
odometer = lastValidOdometer;
} else {
lastValidOdometer = odometer; // Update last valid odometer
}
const servicesPerformed = Array.from(servicesPerformedElement?.querySelectorAll('li') || [])
.map(li => li.textContent.trim())
.join(', ');
const shop = shopElement ? shopElement.textContent.trim() : '';
const shopLink = shopLinkElement ? shopLinkElement.href : '';
// Use Markdown formatting for the shop name with a link
const notes = shopLink ? `[${shop}](${shopLink})` : shop;
// Add to service records
serviceRecords.push({
Date: dateServiced,
Odometer: parseInt(odometer, 10), // Ensure numeric value
Description: servicesPerformed,
Notes: notes,
Cost: 0 // Numeric cost
});
});
// Log records to the console or export as CSV
console.table(serviceRecords);
// Optionally download as CSV
const csvContent = "data:text/csv;charset=utf-8," +
["Date,Odometer,Description,Notes,Cost"]
.concat(serviceRecords.map(record =>
`"${record.Date}",${record.Odometer},"${record.Description}","${record.Notes}",${record.Cost}`)
).join("\n");
const encodedUri = encodeURI(csvContent);
const link = document.createElement("a");
link.setAttribute("href", encodedUri);
link.setAttribute("download", "service_records.csv");
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment