Spanish Vehicle Registration API: Complete Guide to Vehicle and Motorcycle Data Lookup in Spain
https://www.matriculaapi.com/
Spain maintains a comprehensive vehicle registration system managed by the Dirección General de Tráfico (DGT), covering over 25 million registered vehicles across the Iberian Peninsula, Balearic Islands, Canary Islands, and Spanish territories. The Spanish Vehicle Registration API provides developers and businesses with access to detailed vehicle specifications, technical data, and theft status information for both cars and motorcycles registered throughout Spain.
Overview of Spanish Vehicle Registration System
Spain’s vehicle registration is centralized under the DGT (Dirección General de Tráfico), which maintains detailed records for all vehicles operating on Spanish roads. The system provides comprehensive data including technical specifications, variant information, and critical safety indicators such as stolen vehicle status.
Spanish license plates have evolved through several formats:
- Current format (2000-present): Four numbers + three letters (1234 ABC)
- Previous format: Letters indicating province + numbers + letters
- Special plates: Diplomatic, military, historical, and temporary registrations
Spanish Vehicle API Features
Available Data for Cars
When querying Spanish car registrations through the /CheckSpain endpoint, you can retrieve:
- Make and Model – Complete manufacturer and vehicle model identification
- Registration Year – Year when the vehicle was first registered in Spain
- Registration Date – Exact date of vehicle registration
- Engine Specifications – Engine displacement in cubic centimeters
- Fuel Type – Detailed fuel classification (Diesel, Gasolina, etc.)
- Vehicle Variant – Specific model variant and trim level
- Technical Details – Number of seats, doors, and variant type
- Power Rating – Dynamic power in horsepower
- VIN Number – Vehicle Identification Number when available
- Stolen Status – Critical indicator if vehicle has been reported stolen
- Indicative Price – Reference pricing information
Sample Car Response Format
{
"Description": "RENAULT MEGANE",
"CarMake": {
"CurrentTextValue": "RENAULT"
},
"CarModel": {
"CurrentTextValue": "MEGANE"
},
"MakeDescription": {
"CurrentTextValue": "RENAULT"
},
"ModelDescription": {
"CurrentTextValue": "MEGANE"
},
"EngineSize": "1461",
"VehicleIdentificationNumber": null,
"RegistrationYear": "2010",
"RegistrationDate": "06/07/2010",
"Variation": "EXPRESSION 1.5DCI 85",
"Seats": null,
"VariantType": "Diesel 1461 cc 5 puertas",
"VehicleType": "Car",
"Fuel": "Diesel",
"IndicativePrice": null,
"Doors": "5",
"AllTerain": null,
"DynamicPower": "85.0",
"Stolen": null
}
Spanish Motorcycle API
Dedicated Motorcycle Endpoint
For motorcycles and scooters registered in Spain, use the specialized motorcycle endpoint: https://www.matriculaapi.com/api/bespokeapi.asmx?op=CheckMotorBikeSpain
This endpoint returns motorcycle-specific data optimized for two-wheeled vehicles.
Available Data for Motorcycles
When querying Spanish motorcycle registrations, you can retrieve:
- Make and Model – Motorcycle manufacturer and model identification
- Registration Year – Year of first registration in Spain
- Registration Date – Exact registration date
- Engine Size – Engine displacement in cubic centimeters
- Fuel Type – Fuel classification (typically Gasolina for motorcycles)
- Variant – Specific motorcycle variant and version
- Number of Seats – Rider and passenger capacity
- Indicative Price – Reference pricing information
- Transmission Type – Manual or automatic transmission
- Dynamic Power – Power output in horsepower
- Stolen Status – Critical theft indicator
- VIN Number – Vehicle Identification Number when available
Sample Motorcycle Response Format
{
"Description": "SUZUKI DL 650 V-STROM",
"CarMake": {
"CurrentTextValue": "SUZUKI"
},
"CarModel": {
"CurrentTextValue": "DL 650"
},
"MakeDescription": {
"CurrentTextValue": "SUZUKI"
},
"ModelDescription": {
"CurrentTextValue": "DL 650"
},
"EngineSize": "645",
"VehicleIdentificationNumber": "",
"RegistrationYear": "2003",
"RegistrationDate": "01/11/2003",
"Variation": "V-STROM",
"Seats": 1,
"VariantType": "",
"VehicleType": "MOTOCICLETA",
"Fuel": "GASOLINA",
"IndicativePrice": "7909.79",
"Doors": 0,
"AllTerain": 0,
"KType": 0,
"Transmission": "MANUAL",
"DynamicPower": "68",
"Stolen": null
}
API Implementation
Endpoint Usage
The Spanish Vehicle API uses two primary endpoints:
- Cars:
/CheckSpain– For passenger vehicles, vans, and trucks - Motorcycles:
/CheckMotorBikeSpain– For motorcycles, scooters, and mopeds
Both endpoints require:
- Registration Number – The complete Spanish license plate number
- Username – Your API authentication credentials
Basic Implementation Example
// JavaScript example for Spanish vehicle lookup
class SpanishVehicleAPI {
constructor(username) {
this.username = username;
this.carUrl = "https://www.matriculaapi.com/api/reg.asmx/CheckSpain";
this.motorcycleUrl = "https://www.matriculaapi.com/api/bespokeapi.asmx/CheckMotorBikeSpain";
}
async lookupCar(registrationNumber) {
const apiUrl = `${this.carUrl}?RegistrationNumber=${registrationNumber}&username=${this.username}`;
try {
const response = await fetch(apiUrl);
const xmlText = await response.text();
// Parse XML response
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
const jsonData = xmlDoc.getElementsByTagName("vehicleJson")[0].textContent;
const vehicleInfo = JSON.parse(jsonData);
return {
type: 'car',
make: vehicleInfo.MakeDescription.CurrentTextValue,
model: vehicleInfo.ModelDescription.CurrentTextValue,
year: vehicleInfo.RegistrationYear,
registrationDate: vehicleInfo.RegistrationDate,
engineSize: vehicleInfo.EngineSize,
fuel: vehicleInfo.Fuel,
power: vehicleInfo.DynamicPower,
variant: vehicleInfo.Variation,
variantType: vehicleInfo.VariantType,
doors: vehicleInfo.Doors,
seats: vehicleInfo.Seats,
vin: vehicleInfo.VehicleIdentificationNumber,
kType: vehicleInfo.KType,
stolen: vehicleInfo.Stolen,
indicativePrice: vehicleInfo.IndicativePrice
};
} catch (error) {
console.error('Spanish car lookup failed:', error);
return null;
}
}
async lookupMotorcycle(registrationNumber) {
const apiUrl = `${this.motorcycleUrl}?RegistrationNumber=${registrationNumber}&username=${this.username}`;
try {
const response = await fetch(apiUrl);
const xmlText = await response.text();
// Parse XML response
const parser = new DOMParser();
const xmlDoc = parser.parseFromString(xmlText, "text/xml");
const jsonData = xmlDoc.getElementsByTagName("vehicleJson")[0].textContent;
const motorcycleInfo = JSON.parse(jsonData);
return {
type: 'motorcycle',
make: motorcycleInfo.MakeDescription.CurrentTextValue,
model: motorcycleInfo.ModelDescription.CurrentTextValue,
year: motorcycleInfo.RegistrationYear,
registrationDate: motorcycleInfo.RegistrationDate,
engineSize: motorcycleInfo.EngineSize,
fuel: motorcycleInfo.Fuel,
power: motorcycleInfo.DynamicPower,
variant: motorcycleInfo.Variation,
seats: motorcycleInfo.Seats,
transmission: motorcycleInfo.Transmission,
vin: motorcycleInfo.VehicleIdentificationNumber,
stolen: motorcycleInfo.Stolen,
indicativePrice: motorcycleInfo.IndicativePrice
};
} catch (error) {
console.error('Spanish motorcycle lookup failed:', error);
return null;
}
}
async lookupWithAutoDetect(registrationNumber) {
// Try car lookup first
let result = await this.lookupCar(registrationNumber);
if (result && result.make) {
return result;
}
// If car lookup fails, try motorcycle
result = await this.lookupMotorcycle(registrationNumber);
return result;
}
}
// Usage examples
const api = new SpanishVehicleAPI("your_username");
// Car lookup
api.lookupCar("5428GXS").then(data => {
if (data) {
console.log(`Car: ${data.make} ${data.model} (${data.year})`);
console.log(`Engine: ${data.engineSize}cc ${data.fuel}`);
console.log(`Power: ${data.power}HP`);
console.log(`Variant: ${data.variant}`);
if (data.stolen) {
console.warn('⚠️ VEHICLE REPORTED STOLEN');
}
}
});
// Motorcycle lookup
api.lookupMotorcycle("1234ABC").then(data => {
if (data) {
console.log(`Motorcycle: ${data.make} ${data.model} (${data.year})`);
console.log(`Engine: ${data.engineSize}cc`);
console.log(`Power: ${data.power}HP`);
console.log(`Transmission: ${data.transmission}`);
}
});
// Auto-detect vehicle type
api.lookupWithAutoDetect("5428GXS").then(data => {
if (data) {
console.log(`${data.type}: ${data.make} ${data.model}`);
}
});
Python Implementation
import requests
import xml.etree.ElementTree as ET
import json
class SpanishVehicleAPI:
def __init__(self, username):
self.username = username
self.car_url = "https://www.matriculaapi.com/api/reg.asmx/CheckSpain"
self.motorcycle_url = "https://www.matriculaapi.com/api/bespokeapi.asmx/CheckMotorBikeSpain"
def validate_spanish_registration(self, registration):
"""Validate Spanish registration number format"""
if not registration:
return False, "Registration number is required"
# Remove spaces and convert to uppercase
reg = registration.replace(" ", "").upper()
# Spanish format: 4 numbers + 3 letters (modern format)
if len(reg) < 6 or len(reg) > 8:
return False, "Invalid registration length"
return True, reg
def lookup_car(self, registration_number):
"""Lookup Spanish car with comprehensive error handling"""
is_valid, processed_reg = self.validate_spanish_registration(registration_number)
if not is_valid:
return {"error": processed_reg}
try:
params = {
'RegistrationNumber': processed_reg,
'username': self.username
}
response = requests.get(self.car_url, params=params, timeout=15)
response.raise_for_status()
# Parse XML response
root = ET.fromstring(response.content)
json_element = root.find('.//vehicleJson')
if json_element is None or not json_element.text:
return {"error": "No car data found for this registration number"}
vehicle_data = json.loads(json_element.text)
return {
'success': True,
'type': 'car',
'description': vehicle_data.get('Description'),
'make': vehicle_data.get('MakeDescription', {}).get('CurrentTextValue'),
'model': vehicle_data.get('ModelDescription', {}).get('CurrentTextValue'),
'registration_year': vehicle_data.get('RegistrationYear'),
'registration_date': vehicle_data.get('RegistrationDate'),
'engine_size': vehicle_data.get('EngineSize'),
'fuel_type': vehicle_data.get('Fuel'),
'power_hp': vehicle_data.get('DynamicPower'),
'variant': vehicle_data.get('Variation'),
'variant_type': vehicle_data.get('VariantType'),
'doors': vehicle_data.get('Doors'),
'seats': vehicle_data.get('Seats'),
'vin': vehicle_data.get('VehicleIdentificationNumber'),
'k_type': vehicle_data.get('KType'),
'stolen': vehicle_data.get('Stolen'),
'indicative_price': vehicle_data.get('IndicativePrice'),
'all_terrain': vehicle_data.get('AllTerain'),
'raw_data': vehicle_data
}
except Exception as e:
return {"error": f"Car lookup failed: {str(e)}"}
def lookup_motorcycle(self, registration_number):
"""Lookup Spanish motorcycle"""
is_valid, processed_reg = self.validate_spanish_registration(registration_number)
if not is_valid:
return {"error": processed_reg}
try:
params = {
'RegistrationNumber': processed_reg,
'username': self.username
}
response = requests.get(self.motorcycle_url, params=params, timeout=15)
response.raise_for_status()
# Parse XML response
root = ET.fromstring(response.content)
json_element = root.find('.//vehicleJson')
if json_element is None or not json_element.text:
return {"error": "No motorcycle data found for this registration number"}
motorcycle_data = json.loads(json_element.text)
return {
'success': True,
'type': 'motorcycle',
'description': motorcycle_data.get('Description'),
'make': motorcycle_data.get('MakeDescription', {}).get('CurrentTextValue'),
'model': motorcycle_data.get('ModelDescription', {}).get('CurrentTextValue'),
'registration_year': motorcycle_data.get('RegistrationYear'),
'registration_date': motorcycle_data.get('RegistrationDate'),
'engine_size': motorcycle_data.get('EngineSize'),
'fuel_type': motorcycle_data.get('Fuel'),
'power_hp': motorcycle_data.get('DynamicPower'),
'variant': motorcycle_data.get('Variation'),
'seats': motorcycle_data.get('Seats'),
'transmission': motorcycle_data.get('Transmission'),
'vin': motorcycle_data.get('VehicleIdentificationNumber'),
'stolen': motorcycle_data.get('Stolen'),
'indicative_price': motorcycle_data.get('IndicativePrice'),
'raw_data': motorcycle_data
}
except Exception as e:
return {"error": f"Motorcycle lookup failed: {str(e)}"}
def lookup_with_auto_detect(self, registration_number):
"""Try both car and motorcycle endpoints automatically"""
# Try car first
result = self.lookup_car(registration_number)
if result.get('success'):
return result
# Try motorcycle if car lookup fails
result = self.lookup_motorcycle(registration_number)
if result.get('success'):
return result
return {"error": "Vehicle not found in car or motorcycle databases"}
# Usage examples
api = SpanishVehicleAPI("your_username")
# Car lookup
car_result = api.lookup_car("5428GXS")
if car_result.get('success'):
print(f"Car: {car_result['make']} {car_result['model']}")
print(f"Year: {car_result['registration_year']}")
print(f"Engine: {car_result['engine_size']}cc {car_result['fuel_type']}")
print(f"Power: {car_result['power_hp']}HP")
print(f"Variant: {car_result['variant']}")
if car_result['stolen']:
print("⚠️ WARNING: VEHICLE REPORTED STOLEN")
# Motorcycle lookup
bike_result = api.lookup_motorcycle("1234ABC")
if bike_result.get('success'):
print(f"Motorcycle: {bike_result['make']} {bike_result['model']}")
print(f"Engine: {bike_result['engine_size']}cc")
print(f"Power: {bike_result['power_hp']}HP")
print(f"Transmission: {bike_result['transmission']}")
# Auto-detect vehicle type
auto_result = api.lookup_with_auto_detect("5428GXS")
if auto_result.get('success'):
print(f"Vehicle Type: {auto_result['type']}")
print(f"Vehicle: {auto_result['make']} {auto_result['model']}")
Spanish Vehicle Registration Format
Current Format (2000-Present)
Spanish license plates use the format: 1234 ABC
- Four numbers: Sequential numbering (0000-9999)
- Three letters: Alphabetical sequence (avoiding vowels and confusing letters)
- No regional identification in current system
Historical Formats
- Provincial system (1971-2000): Letters indicating province + numbers + letters
- Examples: M-1234-AB (Madrid), B-5678-CD (Barcelona)
Special Registration Plates
- Diplomatic: Special CD series with different formatting
- Historical: H prefix for vintage vehicles over 30 years old
- Temporary: Red plates for unregistered vehicles
- Military: Special military identification series
- Motorcycle: Same format as cars but typically on smaller plates
Understanding Spanish Vehicle Data
Fuel Type Classifications
Spanish fuel type terminology:
- Gasolina – Petrol/Gasoline
- Diesel – Diesel fuel
- Eléctrico – Electric vehicle
- Híbrido – Hybrid vehicle
- GLP – Liquefied Petroleum Gas (Autogas)
- Gas Natural – Compressed Natural Gas
Vehicle Type Classifications
- Turismo – Passenger car
- Furgoneta – Van
- Camión – Truck
- Motocicleta – Motorcycle
- Ciclomotor – Moped
- Quad – All-terrain quad vehicle
Stolen Vehicle Indicator
The Stolen field is critical for security:
- null – No theft report on record
- “Yes” or populated value – Vehicle reported stolen to DGT
- Always check this field before processing vehicle transactions
Spanish Motorcycle Market
Popular Spanish Motorcycle Brands
While Spain is home to fewer motorcycle manufacturers than some European countries, it has a strong motorcycle culture:
Spanish Manufacturers:
- RIEJU – Off-road and enduro motorcycles
- Gas Gas – Trial and enduro specialists
- Derbi – Scooters and small displacement motorcycles (now part of Piaggio)
- Bultaco – Historic brand with recent electric motorcycle revival
- Ossa – Classic motorcycle manufacturer
Popular International Brands in Spain:
- Honda – Leading market share in Spain
- Yamaha – Popular for both scooters and motorcycles
- Suzuki – Strong presence in touring and adventure segments
- BMW – Premium motorcycle segment leader
- Harley-Davidson – Cruiser market leader
Motorcycle Registration Specifics
Spanish motorcycles follow the same registration format as cars but with motorcycle-specific data:
- Detailed engine displacement tracking
- Power output in horsepower
- Transmission type (manual vs automatic/semi-automatic)
- Seating capacity (rider only or with passenger)
Use Cases for Spanish Vehicle API
Insurance Industry
- Premium Calculations – Engine size and power ratings for risk assessment
- Claims Processing – Verify vehicle specifications during claims
- Stolen Vehicle Checks – Critical fraud prevention through stolen status
- Motorcycle Insurance – Specialized data for two-wheeled vehicle policies
Automotive and Motorcycle Dealers
- Trade-In Valuations – Indicative pricing and specification verification
- Vehicle History – Registration date and variant confirmation
- Fraud Prevention – Stolen vehicle status before purchase
- Inventory Management – Automated vehicle data for listings
Fleet Management
- Asset Tracking – Comprehensive vehicle identification for cars and motorcycles
- Compliance Monitoring – Ensure proper registration across fleet
- Theft Monitoring – Regular stolen status checks for fleet vehicles
- Maintenance Planning – Engine specifications for service schedules
Law Enforcement
- Vehicle Identification – Quick lookups during traffic stops
- Stolen Vehicle Detection – Immediate access to theft indicators
- Investigation Support – Vehicle history and specification verification
- Motorcycle Enforcement – Dedicated motorcycle data for traffic control
Mobile Applications
- Insurance Apps – Instant vehicle verification for quotes
- Marketplace Apps – Vehicle specification for classified listings
- Service Booking – Technical specs for maintenance appointments
- Parking Apps – Vehicle type identification for permit validation
Error Handling and Security Considerations
class SecureSpanishVehicleAPI extends SpanishVehicleAPI {
constructor(username) {
super(username);
this.maxRetries = 3;
this.retryDelay = 1000; // milliseconds
}
async lookupWithSecurity(registrationNumber, vehicleType = 'auto') {
// Validate input to prevent injection
if (!this.validateInput(registrationNumber)) {
return {
error: true,
message: "Invalid registration format",
security: "Input validation failed"
};
}
// Perform lookup with retry logic
let lastError;
for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
try {
let result;
if (vehicleType === 'car') {
result = await this.lookupCar(registrationNumber);
} else if (vehicleType === 'motorcycle') {
result = await this.lookupMotorcycle(registrationNumber);
} else {
result = await this.lookupWithAutoDetect(registrationNumber);
}
// Check for stolen vehicle
if (result && result.stolen) {
console.warn(`SECURITY ALERT: Vehicle ${registrationNumber} reported stolen`);
result.securityAlert = "STOLEN_VEHICLE";
}
return result;
} catch (error) {
lastError = error;
if (attempt < this.maxRetries) {
await new Promise(resolve =>
setTimeout(resolve, this.retryDelay * attempt)
);
}
}
}
return {
error: true,
message: `Lookup failed after ${this.maxRetries} attempts`,
details: lastError.message
};
}
validateInput(registration) {
// Prevent SQL injection and XSS
if (!registration || typeof registration !== 'string') {
return false;
}
// Check for suspicious characters
const suspiciousPattern = /[;<>'"\\]/;
if (suspiciousPattern.test(registration)) {
return false;
}
return true;
}
}
Data Privacy and Compliance
GDPR Compliance
Spain follows strict EU data protection regulations:
- Vehicle technical data is not personal information
- Registration numbers are public vehicle identifiers
- Implement proper data retention policies
- Ensure secure handling of stolen vehicle information
Security Best Practices
- Always check stolen status before vehicle transactions
- Log all stolen vehicle alerts for audit trails
- Implement rate limiting to prevent abuse
- Secure API credentials and use HTTPS only
Getting Started
Account Registration
- Sign Up – Register for Spanish vehicle API access
- Verification – Complete business verification process
- Testing – Use sample registrations for development:
- Cars: “5428GXS” (Renault Megane from documentation)
- Motorcycles: Test with various Spanish motorcycle plates
- Production – Configure both car and motorcycle endpoints
Integration Checklist
- [ ] Implement both car and motorcycle endpoints
- [ ] Add stolen vehicle status checking and alerting
- [ ] Create auto-detect logic for vehicle type
- [ ] Design UI for Spanish registration format
- [ ] Implement security validation for inputs
- [ ] Add logging for stolen vehicle alerts
- [ ] Test with both modern and historical plate formats
Sample Data for Testing
- Cars: 5428GXS (Renault Megane Diesel)
- Motorcycles: Various Spanish motorcycle registrations
- Stolen checks: Verify stolen status handling
Conclusion
The Spanish Vehicle Registration API provides comprehensive access to Spain’s vehicle database, offering detailed technical specifications for both cars and motorcycles. The system’s inclusion of stolen vehicle indicators makes it particularly valuable for fraud prevention and security applications, while the dedicated motorcycle endpoint ensures proper data handling for Spain’s significant two-wheeled vehicle population.
Spain’s centralized DGT system ensures consistent data quality while the API’s dual endpoint approach allows for optimized data retrieval for different vehicle types. Understanding Spanish fuel classifications, registration formats, and the critical importance of stolen vehicle checking enhances the effectiveness of API integration.
The motorcycle-specific endpoint recognizes Spain’s vibrant motorcycle culture and provides specialized data fields for transmission types, seating configurations, and power ratings appropriate for two-wheeled vehicles.
Begin accessing Spanish vehicle data by registering for API credentials and exploring the comprehensive database covering cars and motorcycles across all Spanish regions and territories. Always implement stolen vehicle status checking to ensure secure and compliant vehicle data operations.
https://www.matriculaapi.com/