Building a Power Adapter Checker for Travel Apps

javascript
// Check power compatibility: US traveler going to Japan
const response = await fetch("https://worlddataapi.com/v1/travel/JP?from=US", {
	headers: { "X-API-Key": "YOUR_API_KEY" },
});
const data = await response.json();

console.log(data.power);
// {
//   "plugs": ["A", "B"],
//   "voltage": 100,
//   "power_hz": 50
// }

console.log(data.power_compatibility);
// {
//   "adapter_needed": false,
//   "voltage_compatible": true,
//   "shared_plugs": ["A", "B"]
// }
python
import requests

# Check power compatibility: US traveler going to Japan
response = requests.get(
    "https://worlddataapi.com/v1/travel/JP?from=US",
    headers={"X-API-Key": "YOUR_API_KEY"}
)
data = response.json()

print(data["power"])
# {
#   "plugs": ["A", "B"],
#   "voltage": 100,
#   "power_hz": 50
# }

print(data["power_compatibility"])
# {
#   "adapter_needed": False,
#   "voltage_compatible": True,
#   "shared_plugs": ["A", "B"]
# }
bash
# Check power compatibility: US traveler going to Japan
curl -X GET "https://worlddataapi.com/v1/travel/JP?from=US" \
  -H "X-API-Key: YOUR_API_KEY"

Travelers don't want to discover they need a power adapter when their phone is at 3%. This guide covers building a power compatibility checker that tells users exactly what they need before they leave home.

The Challenge#

Power standards vary wildly around the world. The US and Japan use 100-127V with Type A/B plugs. Europe uses 220-240V with Type C/E/F plugs. The UK has its own Type G standard. Brazil recently adopted a unique Type N plug found nowhere else.

Building a reliable power compatibility checker means handling:

  • 15 different plug types defined by IEC 60083, with some countries using multiple types

  • Two voltage standards (100-127V and 220-240V) that can damage incompatible devices

  • Regional variations within countries (Brazil uses both 127V and 220V depending on the region)

  • Partial compatibility where some plug types fit but voltage differs

Hardcoding this data is error-prone and difficult to maintain. An API-based approach keeps your app current as standards occasionally change.

Prerequisites#

Before starting, you need:

  • A World Data API account with a Starter plan or higher (travel data is a premium endpoint)

  • Your API key from the dashboard

  • Basic knowledge of JavaScript/React or Python

  • Node.js 16+ or Python 3.8+ installed locally

Understanding Power Standards#

Three factors determine compatibility:

FactorDescriptionImpact
Plug TypePhysical shape (A, B, C, etc.)Wrong shape = won't fit outlet
Voltage100V to 240VWrong voltage = damage device
Frequency50Hz or 60HzUsually doesn't matter for modern electronics

Plug Types#

The world uses about 15 different plug types, defined by IEC 60083:

javascript
const PLUG_TYPES = {
	A: {
		name: "Type A",
		pins: 2,
		grounded: false,
		regions: ["North America", "Japan"],
	},
	B: {
		name: "Type B",
		pins: 3,
		grounded: true,
		regions: ["North America", "Japan"],
	},
	C: {
		name: "Type C (Europlug)",
		pins: 2,
		grounded: false,
		regions: ["Europe", "South America"],
	},
	D: { name: "Type D", pins: 3, grounded: true, regions: ["India"] },
	E: {
		name: "Type E",
		pins: 2,
		grounded: true,
		regions: ["France", "Belgium"],
	},
	F: {
		name: "Type F (Schuko)",
		pins: 2,
		grounded: true,
		regions: ["Germany", "Europe"],
	},
	G: {
		name: "Type G",
		pins: 3,
		grounded: true,
		regions: ["UK", "Ireland", "Singapore"],
	},
	H: { name: "Type H", pins: 3, grounded: true, regions: ["Israel"] },
	I: {
		name: "Type I",
		pins: 3,
		grounded: true,
		regions: ["Australia", "China"],
	},
	J: { name: "Type J", pins: 3, grounded: true, regions: ["Switzerland"] },
	K: { name: "Type K", pins: 3, grounded: true, regions: ["Denmark"] },
	L: { name: "Type L", pins: 3, grounded: true, regions: ["Italy"] },
	M: { name: "Type M", pins: 3, grounded: true, regions: ["South Africa"] },
	N: { name: "Type N", pins: 3, grounded: true, regions: ["Brazil"] },
	O: { name: "Type O", pins: 3, grounded: true, regions: ["Thailand"] },
};

Voltage Standards#

The world splits into two main voltage camps:

javascript
const VOLTAGE_REGIONS = {
	low: { range: [100, 127], countries: ["US", "CA", "JP", "MX", "TW"] },
	high: { range: [220, 240], countries: ["Most of Europe, Asia, Africa"] },
};

// Japan is unique at 100V — the lowest standard voltage

Basic Compatibility Check#

javascript
async function checkPowerCompatibility(origin, destination) {
	const response = await fetch(
		`https://worlddataapi.com/v1/travel/${destination}?from=${origin}`,
		{ headers: { "X-API-Key": API_KEY } },
	);
	const data = await response.json();

	return {
		destination: data.destination,
		destinationPower: data.power,
		compatibility: data.power_compatibility,
		recommendations: generateRecommendations(data),
	};
}

function generateRecommendations(data) {
	const recommendations = [];
	const { power, power_compatibility } = data;

	// Adapter recommendation
	if (power_compatibility.adapter_needed) {
		const neededPlugs = power.plugs.filter(
			(p) => !power_compatibility.shared_plugs.includes(p),
		);
		recommendations.push({
			type: "adapter",
			priority: "required",
			message: `You need an adapter for Type ${neededPlugs.join("/")} outlets`,
			detail: `Your plugs won't fit ${data.destination} outlets`,
		});
	}

	// Voltage warning
	if (!power_compatibility.voltage_compatible) {
		recommendations.push({
			type: "voltage",
			priority: "critical",
			message: `Voltage difference: Your devices may not be compatible`,
			detail: `${data.destination} uses ${power.voltage}V. Check your device labels.`,
		});
	}

	return recommendations;
}

Building the UI#

jsx
function PowerCompatibilityChecker() {
	const [origin, setOrigin] = useState("");
	const [destination, setDestination] = useState("");
	const [result, setResult] = useState(null);
	const [loading, setLoading] = useState(false);

	const checkCompatibility = async () => {
		if (!origin || !destination) return;

		setLoading(true);
		try {
			const data = await checkPowerCompatibility(origin, destination);
			setResult(data);
		} finally {
			setLoading(false);
		}
	};

	return (
		<div className="power-checker">
			<h2>Power Adapter Checker</h2>

			<div className="inputs">
				<CountrySelector
					label="Traveling from"
					value={origin}
					onChange={setOrigin}
				/>
				<CountrySelector
					label="Traveling to"
					value={destination}
					onChange={setDestination}
				/>
				<button onClick={checkCompatibility} disabled={loading}>
					{loading ? "Checking..." : "Check Compatibility"}
				</button>
			</div>

			{result && <PowerResult result={result} />}
		</div>
	);
}

function PowerResult({ result }) {
	const { destinationPower, compatibility, recommendations } = result;

	return (
		<div className="power-result">
			<div className="destination-info">
				<h3>{result.destination} Power Standards</h3>
				<dl>
					<dt>Plug Types</dt>
					<dd>
						{destinationPower.plugs.map((type) => (
							<PlugIcon key={type} type={type} />
						))}
					</dd>
					<dt>Voltage</dt>
					<dd>{destinationPower.voltage}V</dd>
					<dt>Frequency</dt>
					<dd>{destinationPower.power_hz}Hz</dd>
				</dl>
			</div>

			<div className="compatibility-status">
				{compatibility.adapter_needed ? (
					<div className="status warning">
						<span className="icon">⚠️</span>
						<span>Adapter Required</span>
					</div>
				) : (
					<div className="status success">
						<span className="icon"></span>
						<span>Your plugs will fit</span>
					</div>
				)}

				{!compatibility.voltage_compatible && (
					<div className="status error">
						<span className="icon"></span>
						<span>Voltage Warning</span>
					</div>
				)}
			</div>

			{recommendations.length > 0 && (
				<div className="recommendations">
					<h4>What You Need</h4>
					{recommendations.map((rec, i) => (
						<Recommendation key={i} {...rec} />
					))}
				</div>
			)}
		</div>
	);
}

Plug Type Visualization#

Display plug types visually so users know what to look for:

jsx
function PlugIcon({ type, size = 48 }) {
	// Use SVG icons or images for each plug type
	const plugImages = {
		A: "/images/plugs/type-a.svg",
		B: "/images/plugs/type-b.svg",
		C: "/images/plugs/type-c.svg",
		// ... etc
	};

	const plugInfo = PLUG_TYPES[type];

	return (
		<div className="plug-icon" title={plugInfo?.name}>
			<img
				src={plugImages[type]}
				alt={`Type ${type} plug`}
				width={size}
				height={size}
			/>
			<span className="plug-label">Type {type}</span>
		</div>
	);
}

// Alternative: CSS-based plug representation
function PlugDiagram({ type }) {
	const plugConfig = {
		A: {
			pins: [
				{ x: 30, y: 50 },
				{ x: 70, y: 50 },
			],
			shape: "flat",
		},
		B: {
			pins: [
				{ x: 25, y: 40 },
				{ x: 75, y: 40 },
				{ x: 50, y: 70 },
			],
			shape: "flat",
		},
		C: {
			pins: [
				{ x: 30, y: 50 },
				{ x: 70, y: 50 },
			],
			shape: "round",
		},
		G: {
			pins: [
				{ x: 50, y: 30 },
				{ x: 25, y: 65 },
				{ x: 75, y: 65 },
			],
			shape: "rect",
		},
	};

	const config = plugConfig[type];
	if (!config) return <span>Type {type}</span>;

	return (
		<svg viewBox="0 0 100 100" className="plug-diagram">
			<rect
				x="10"
				y="10"
				width="80"
				height="80"
				rx="5"
				fill="#f5f5f5"
				stroke="#ccc"
			/>
			{config.pins.map((pin, i) => (
				<circle
					key={i}
					cx={pin.x}
					cy={pin.y}
					r={config.shape === "round" ? 6 : 4}
					fill="#333"
				/>
			))}
			<text x="50" y="95" textAnchor="middle" fontSize="10">
				Type {type}
			</text>
		</svg>
	);
}

Voltage Compatibility Details#

Help users understand the voltage situation:

jsx
function VoltageInfo({ originVoltage, destVoltage }) {
	const compatible = isVoltageCompatible(originVoltage, destVoltage);

	return (
		<div className={`voltage-info ${compatible ? "safe" : "warning"}`}>
			<h4>Voltage Compatibility</h4>

			<div className="voltage-comparison">
				<div className="voltage origin">
					<span className="label">Your Country</span>
					<span className="value">{originVoltage}V</span>
				</div>
				<div className="arrow">{compatible ? "✓" : "→"}</div>
				<div className="voltage destination">
					<span className="label">Destination</span>
					<span className="value">{destVoltage}V</span>
				</div>
			</div>

			{!compatible && (
				<div className="voltage-warning">
					<h5>⚠️ Voltage Difference Detected</h5>
					<p>
						Most modern electronics (phones, laptops, cameras) have
						universal power supplies that work with 100-240V. Check
						the label on your charger—if it says "100-240V", you're
						fine.
					</p>
					<p>
						<strong>Be careful with:</strong> Hair dryers, curling
						irons, electric razors, and other appliances without
						universal power supplies. These may need a voltage
						converter, not just an adapter.
					</p>
				</div>
			)}

			{compatible && (
				<div className="voltage-safe">
					<p>
						 Your electronics will work without a voltage
						converter.
					</p>
				</div>
			)}
		</div>
	);
}

function isVoltageCompatible(origin, dest) {
	// Most modern electronics handle 100-240V
	// Flag only extreme differences
	const lowVoltage = [100, 110, 120, 127];
	const highVoltage = [220, 230, 240];

	const originIsLow = lowVoltage.includes(origin);
	const destIsLow = lowVoltage.includes(dest);

	// Same voltage range = compatible
	return originIsLow === destIsLow;
}

Device-Specific Advice#

jsx
function DeviceChecklist({ originVoltage, destVoltage }) {
	const voltageMismatch = !isVoltageCompatible(originVoltage, destVoltage);

	const devices = [
		{
			name: "Phone/Tablet charger",
			icon: "phone",
			universal: true,
			advice: "Usually works worldwide (100-240V). Check the charger label.",
		},
		{
			name: "Laptop charger",
			icon: "laptop",
			universal: true,
			advice: 'Most laptop chargers are universal. Verify "100-240V" on label.',
		},
		{
			name: "Camera battery charger",
			icon: "camera",
			universal: true,
			advice: "Typically universal, but check the label to be sure.",
		},
		{
			name: "Hair dryer",
			icon: "hairdryer",
			universal: false,
			advice: voltageMismatch
				? "WARNING: Usually NOT universal. May need voltage converter or buy one locally."
				: "Should work, but verify voltage on the device.",
		},
		{
			name: "Electric razor",
			icon: "razor",
			universal: false,
			advice: voltageMismatch
				? "Check if dual-voltage. Many travel razors support 100-240V."
				: "Should work with correct adapter.",
		},
		{
			name: "Curling iron/Straightener",
			icon: "styling",
			universal: false,
			advice: voltageMismatch
				? "WARNING: Usually single-voltage. Consider a travel version or buy locally."
				: "Check voltage rating before use.",
		},
	];

	return (
		<div className="device-checklist">
			<h4>Device Compatibility</h4>
			<ul>
				{devices.map((device) => (
					<li
						key={device.name}
						className={device.universal ? "safe" : "caution"}
					>
						<DeviceIcon name={device.icon} />
						<div className="device-info">
							<strong>{device.name}</strong>
							<p>{device.advice}</p>
						</div>
					</li>
				))}
			</ul>
		</div>
	);
}

Adapter Recommendations#

Help users buy the right adapter:

jsx
function AdapterRecommendation({ originPlugs, destPlugs, sharedPlugs }) {
	const neededPlugs = destPlugs.filter((p) => !sharedPlugs.includes(p));

	if (neededPlugs.length === 0) {
		return (
			<div className="adapter-rec no-adapter">
				<h4> No Adapter Needed</h4>
				<p>
					Your plugs are compatible with outlets at your destination.
				</p>
			</div>
		);
	}

	return (
		<div className="adapter-rec">
			<h4>Adapter Required</h4>
			<p>You need an adapter that converts your plug to:</p>

			<div className="needed-plugs">
				{neededPlugs.map((type) => (
					<PlugIcon key={type} type={type} />
				))}
			</div>

			<div className="adapter-tips">
				<h5>Shopping Tips</h5>
				<ul>
					<li>
						<strong>Universal adapter:</strong> If you travel often,
						get a universal adapter that works in multiple
						countries.
					</li>
					<li>
						<strong>Multiple outlets:</strong> Consider an adapter
						with multiple USB ports and outlets to charge several
						devices.
					</li>
					<li>
						<strong>Adapter vs. Converter:</strong> An adapter
						changes plug shape. A converter changes voltage. Most
						travelers only need an adapter.
					</li>
				</ul>
			</div>
		</div>
	);
}

Regional Variations#

Some countries have regional differences. Handle them with region-specific lookups:

javascript
async function checkRegionalPower(origin, destination) {
	// Some countries have different standards in different regions
	// The API returns region-specific data when available

	const response = await fetch(
		`https://worlddataapi.com/v1/travel/${destination}?from=${origin}`,
		{ headers: { "X-API-Key": API_KEY } },
	);

	return response.json();
}

// Example: Brazil uses both 127V and 220V depending on region
// The API handles this by returning the regional data when
// a region code is provided (e.g., "BR-SP" for São Paulo)

Packing List Generator#

Generate a complete power-related packing list:

jsx
function PowerPackingList({ compatibility, destPower }) {
	const items = [];

	// Adapter if needed
	if (compatibility.adapter_needed) {
		items.push({
			item: `Power adapter (Type ${destPower.plugs.join("/")})`,
			priority: "essential",
			reason: "Your plugs won't fit local outlets",
		});
	}

	// Universal items everyone should consider
	items.push({
		item: "Portable power bank",
		priority: "recommended",
		reason: "Backup power when outlets aren't available",
	});

	items.push({
		item: "Multi-port USB charger",
		priority: "recommended",
		reason: "Charge multiple devices with one adapter",
	});

	// Voltage converter if needed
	if (!compatibility.voltage_compatible) {
		items.push({
			item: "Voltage converter (if bringing non-universal appliances)",
			priority: "conditional",
			reason: `Destination uses ${destPower.voltage}V`,
		});
	}

	return (
		<div className="packing-list">
			<h4>Power Packing List</h4>
			<ul>
				{items.map((item, i) => (
					<li key={i} className={`priority-${item.priority}`}>
						<input type="checkbox" id={`item-${i}`} />
						<label htmlFor={`item-${i}`}>
							<strong>{item.item}</strong>
							<span className="reason">{item.reason}</span>
						</label>
					</li>
				))}
			</ul>
		</div>
	);
}

Multi-Country Trips#

For trips with multiple destinations:

jsx
function MultiCountryPowerCheck({ origin, destinations }) {
	const [results, setResults] = useState([]);
	const [loading, setLoading] = useState(false);

	useEffect(() => {
		if (destinations.length === 0) return;

		setLoading(true);
		Promise.all(
			destinations.map((dest) => checkPowerCompatibility(origin, dest)),
		)
			.then(setResults)
			.finally(() => setLoading(false));
	}, [origin, destinations]);

	// Find adapters needed for ANY destination
	const allNeededPlugs = new Set();
	const voltageIssues = [];

	results.forEach((result) => {
		if (result.compatibility.adapter_needed) {
			result.destinationPower.plugs.forEach((p) => {
				if (!result.compatibility.shared_plugs.includes(p)) {
					allNeededPlugs.add(p);
				}
			});
		}
		if (!result.compatibility.voltage_compatible) {
			voltageIssues.push({
				country: result.destination,
				voltage: result.destinationPower.voltage,
			});
		}
	});

	return (
		<div className="multi-country-check">
			<h3>Trip Power Summary</h3>

			{allNeededPlugs.size > 0 ? (
				<div className="summary-adapters">
					<h4>Adapters Needed for This Trip</h4>
					<div className="plug-list">
						{[...allNeededPlugs].map((type) => (
							<PlugIcon key={type} type={type} />
						))}
					</div>
					<p className="tip">
						💡 Consider a universal adapter that covers all these
						types.
					</p>
				</div>
			) : (
				<div className="summary-no-adapters">
					<h4> No Adapters Needed</h4>
					<p>Your plugs work in all destinations!</p>
				</div>
			)}

			{voltageIssues.length > 0 && (
				<div className="voltage-warnings">
					<h4>⚠️ Voltage Varies</h4>
					<ul>
						{voltageIssues.map((issue) => (
							<li key={issue.country}>
								{issue.country}: {issue.voltage}V
							</li>
						))}
					</ul>
				</div>
			)}

			<div className="country-details">
				<h4>By Country</h4>
				{results.map((result) => (
					<CountryPowerSummary
						key={result.destination}
						result={result}
					/>
				))}
			</div>
		</div>
	);
}

Styling#

css
.power-checker {
	max-width: 600px;
	margin: 0 auto;
	padding: 20px;
}

.inputs {
	display: flex;
	gap: 16px;
	flex-wrap: wrap;
	margin-bottom: 24px;
}

.power-result {
	background: #f9f9f9;
	border-radius: 8px;
	padding: 20px;
}

.compatibility-status {
	display: flex;
	gap: 16px;
	margin: 16px 0;
}

.status {
	display: flex;
	align-items: center;
	gap: 8px;
	padding: 12px 16px;
	border-radius: 6px;
	font-weight: 500;
}

.status.success {
	background: #d4edda;
	color: #155724;
}

.status.warning {
	background: #fff3cd;
	color: #856404;
}

.status.error {
	background: #f8d7da;
	color: #721c24;
}

.plug-icon {
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	padding: 8px;
	margin: 4px;
	background: white;
	border: 1px solid #ddd;
	border-radius: 4px;
}

.plug-label {
	font-size: 12px;
	margin-top: 4px;
	color: #666;
}

.device-checklist ul {
	list-style: none;
	padding: 0;
}

.device-checklist li {
	display: flex;
	align-items: flex-start;
	gap: 12px;
	padding: 12px;
	border-bottom: 1px solid #eee;
}

.device-checklist li.safe {
	background: #f8fff8;
}

.device-checklist li.caution {
	background: #fffef8;
}

.device-info strong {
	display: block;
	margin-bottom: 4px;
}

.device-info p {
	margin: 0;
	font-size: 14px;
	color: #666;
}

.packing-list ul {
	list-style: none;
	padding: 0;
}

.packing-list li {
	padding: 8px 0;
}

.packing-list label {
	display: flex;
	flex-direction: column;
	margin-left: 8px;
}

.packing-list .reason {
	font-size: 13px;
	color: #666;
}

.priority-essential strong::after {
	content: " (Essential)";
	color: #dc3545;
	font-weight: normal;
}

.priority-conditional strong::after {
	content: " (If needed)";
	color: #ffc107;
	font-weight: normal;
}

Common Pitfalls#

Assuming voltage compatibility means no adapter needed#

A US traveler going to the UK faces compatible voltage (both countries use devices that handle 110-240V) but incompatible plugs. Always check both factors independently.

Ignoring regional variations#

Brazil uses both 127V and 220V depending on the region. The API returns national-level data by default. For more accuracy, query with region codes (e.g., BR-SP for Sao Paulo) when available.

Confusing adapters with converters#

An adapter changes the plug shape so it fits the outlet. A converter changes the voltage. Most modern electronics (phones, laptops, cameras) have universal power supplies and only need adapters. Hair dryers and other heating appliances often need converters.

Not caching the data#

Power standards rarely change. Cache responses for at least 24 hours to reduce API calls and improve response times. Country-level power data can be cached for even longer.

Hardcoding plug compatibility logic#

The relationship between plug types is complex. Type A plugs fit Type B outlets but not vice versa. Type C fits E and F outlets. Let the API handle compatibility logic rather than implementing it yourself.

Summary#

Building a power adapter checker requires handling 15 plug types, two voltage standards, and regional variations. The World Data API travel endpoint provides plug types, voltage, frequency, and pre-computed compatibility data, letting you focus on the user experience rather than maintaining power standards data.

Key implementation points:

  • Query the /v1/travel/{country}?from={origin} endpoint for compatibility data

  • Display plug types visually so users recognize what they need

  • Warn about voltage differences for non-universal devices (hair dryers, curling irons)

  • For multi-country trips, aggregate adapter needs across all destinations

  • Cache responses to reduce API calls

Ready to add power compatibility to your travel app? Get your API key and start building today.