OSM Kenya Boundaries 🇰🇪
A comprehensive TypeScript/JavaScript library providing complete administrative boundary data for Kenya, including all 47 Counties, 290+ Constituencies, and 1,450+ Wards.
✨ Features
- ✅ Complete Data: All 47 counties, 290+ constituencies, and 1,450+ wards
- 🎯 TypeScript Support: Full type definitions included
- 🔍 Search Functions: Easy search and lookup across all administrative levels
- 📦 Zero Dependencies: Lightweight and fast (< 200KB)
- 🌳 Tree-shakeable: Import only what you need
- 📖 Well Documented: Comprehensive examples and API documentation
- 🗺️ OSM Compatible: Data structure optimized for mapping applications
- 🚀 Performance: Optimized for fast queries and low memory usage
📦 Installation
npm install osm-kenya-boundaries
Or using yarn:
yarn add osm-kenya-boundaries
Or using pnpm:
pnpm add osm-kenya-boundaries
🚀 Quick Start
import {
getCounties,
getCountyByName,
getConstituenciesByCounty,
searchWard
} from 'osm-kenya-boundaries';
// Get all counties
const counties = getCounties();
console.log(`Kenya has ${counties.length} counties`);
// Get specific county
const nairobi = getCountyByName('Nairobi');
console.log(nairobi);
// Output: { county_code: 47, county_name: 'Nairobi', constituencies: [...] }
// Get constituencies in a county
const constituencies = getConstituenciesByCounty(47);
console.log(`Nairobi has ${constituencies.length} constituencies`);
// Search for a ward
const results = searchWard('Kilimani');
console.log(results);
📚 API Reference
County Functions
getCounties(): County[]
Returns all 47 counties in Kenya.
const allCounties = getCounties();
console.log(allCounties.length); // 47
getCountyByCode(code: number): County | undefined
Get a county by its numeric code (1-47).
const mombasa = getCountyByCode(1);
const nairobi = getCountyByCode(47);
getCountyByName(name: string): County | undefined
Get a county by name (case-insensitive).
const mombasa = getCountyByName('Mombasa');
const kisumu = getCountyByName('KISUMU'); // Case insensitive
const county = getCountyByName(' Nairobi '); // Handles whitespace
Constituency Functions
getAllConstituencies(): Array<Constituency & { county_name: string; county_code: number }>
Get all constituencies with their parent county information.
const allConstituencies = getAllConstituencies();
allConstituencies.forEach(c => {
console.log(`${c.constituency_name} in ${c.county_name}`);
});
getConstituenciesByCounty(countyCode: number): Constituency[]
Get all constituencies in a specific county.
const nairobiConstituencies = getConstituenciesByCounty(47);
const mombasaConstituencies = getConstituenciesByCounty(1);
getConstituencyByName(name: string): SearchResult | undefined
Find a constituency by name and get its parent county.
const result = getConstituencyByName('Westlands');
console.log(result?.county.county_name); // "Nairobi"
console.log(result?.constituency.wards); // ["Kitisuru", "Parklands/Highridge", ...]
Ward Functions
getAllWards(): Array<{ ward: string; constituency: string; county: string }>
Get all wards with their parent constituency and county.
const allWards = getAllWards();
console.log(`Total wards: ${allWards.length}`);
getWardsByConstituency(constituencyName: string): string[]
Get all wards in a specific constituency.
const westlandsWards = getWardsByConstituency('Westlands');
console.log(westlandsWards);
// ["Kitisuru", "Parklands/Highridge", "Karura", "Kangemi", "Mountain View"]
searchWard(wardName: string): SearchResult[]
Search for wards by name. Returns all matches as some ward names may appear in multiple locations.
const results = searchWard('Central');
results.forEach(result => {
console.log(`${result.ward} in ${result.constituency?.constituency_name}, ${result.county?.county_name}`);
});
Search & Utility Functions
search(query: string): SearchResult[]
Search across all administrative levels (counties, constituencies, and wards).
const results = search('Nairobi');
// Returns matches from counties, constituencies, and wards containing "Nairobi"
validateLocation(county?: string, constituency?: string, ward?: string): boolean
Validate if a location exists in the administrative hierarchy.
// Valid location
const isValid = validateLocation('Nairobi', 'Westlands', 'Kilimani');
console.log(isValid); // true
// Invalid constituency
const isInvalid = validateLocation('Nairobi', 'InvalidConstituency');
console.log(isInvalid); // false
// Partial validation
const countyExists = validateLocation('Mombasa');
console.log(countyExists); // true
getStatistics()
Get statistical information about Kenya's administrative divisions.
const stats = getStatistics();
console.log(stats);
// {
// counties: 47,
// constituencies: 290,
// wards: 1450,
// avgConstituenciesPerCounty: 6.17,
// avgWardsPerConstituency: 5.0
// }
🎯 Use Cases
📝 Form Dropdowns (Cascading Selects)
import { getCounties, getConstituenciesByCounty, getWardsByConstituency } from 'osm-kenya-boundaries';
// Populate county dropdown
const countyOptions = getCounties().map(c => ({
value: c.county_code,
label: c.county_name
}));
// When county is selected
function onCountyChange(countyCode: number) {
const constituencies = getConstituenciesByCounty(countyCode);
// Update constituency dropdown
return constituencies.map(c => ({
value: c.constituency_name,
label: c.constituency_name
}));
}
// When constituency is selected
function onConstituencyChange(constituencyName: string) {
const wards = getWardsByConstituency(constituencyName);
// Update ward dropdown
return wards.map(w => ({
value: w,
label: w
}));
}
✅ Address Validation
import { validateLocation } from 'osm-kenya-boundaries';
interface KenyanAddress {
county: string;
constituency: string;
ward: string;
street?: string;
}
function validateKenyanAddress(address: KenyanAddress): boolean {
const isValid = validateLocation(
address.county,
address.constituency,
address.ward
);
if (!isValid) {
throw new Error('Invalid Kenyan administrative location');
}
return true;
}
// Usage
try {
validateKenyanAddress({
county: 'Nairobi',
constituency: 'Westlands',
ward: 'Kilimani',
street: 'Argwings Kodhek Road'
});
console.log('Address is valid!');
} catch (error) {
console.error(error.message);
}
🔍 Search Autocomplete
import { search } from 'osm-kenya-boundaries';
function autocompleteLocation(query: string) {
if (query.length < 2) return [];
const results = search(query);
return results.map(result => {
if (result.ward) {
return {
label: `${result.ward} Ward, ${result.constituency?.constituency_name}, ${result.county?.county_name}`,
type: 'ward',
value: result
};
} else if (result.constituency) {
return {
label: `${result.constituency.constituency_name} Constituency, ${result.county?.county_name}`,
type: 'constituency',
value: result
};
} else {
return {
label: `${result.county?.county_name} County`,
type: 'county',
value: result
};
}
});
}
// Usage
const suggestions = autocompleteLocation('Nai');
console.log(suggestions);
🗺️ Mapping Applications
import { getCounties, getConstituenciesByCounty } from 'osm-kenya-boundaries';
import L from 'leaflet';
// Create a choropleth map
const counties = getCounties();
const map = L.map('map').setView([-1.286389, 36.817223], 6);
counties.forEach(county => {
const constituencies = county.constituencies;
console.log(`${county.county_name}: ${constituencies.length} constituencies`);
// Add markers or polygons for each county
// You would need GeoJSON data for actual boundary rendering
});
⚛️ React Example
import { useState, useEffect } from 'react';
import {
getCounties,
getConstituenciesByCounty,
getWardsByConstituency,
type County,
type Constituency
} from 'osm-kenya-boundaries';
export function LocationSelector() {
const [selectedCounty, setSelectedCounty] = useState('');
const [selectedConstituency, setSelectedConstituency] = useState('');
const [selectedWard, setSelectedWard] = useState('');
const [constituencies, setConstituencies] = useState<Constituency[]>([]);
const [wards, setWards] = useState<string[]>([]);
const counties = getCounties();
useEffect(() => {
if (selectedCounty) {
const county = counties.find(c => c.county_name === selectedCounty);
if (county) {
const consts = getConstituenciesByCounty(county.county_code);
setConstituencies(consts);
setSelectedConstituency('');
setSelectedWard('');
}
}
}, [selectedCounty]);
useEffect(() => {
if (selectedConstituency) {
const wardList = getWardsByConstituency(selectedConstituency);
setWards(wardList);
setSelectedWard('');
}
}, [selectedConstituency]);
return (
<div className="space-y-4">
<div>
<label className="block text-sm font-medium mb-1">County</label>
<select
value={selectedCounty}
onChange={(e) => setSelectedCounty(e.target.value)}
className="w-full border rounded px-3 py-2"
>
<option value="">Select County</option>
{counties.map(county => (
<option key={county.county_code} value={county.county_name}>
{county.county_name}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium mb-1">Constituency</label>
<select
value={selectedConstituency}
onChange={(e) => setSelectedConstituency(e.target.value)}
className="w-full border rounded px-3 py-2"
disabled={!selectedCounty}
>
<option value="">Select Constituency</option>
{constituencies.map(constituency => (
<option key={constituency.constituency_name} value={constituency.constituency_name}>
{constituency.constituency_name}
</option>
))}
</select>
</div>
<div>
<label className="block text-sm font-medium mb-1">Ward</label>
<select
value={selectedWard}
onChange={(e) => setSelectedWard(e.target.value)}
className="w-full border rounded px-3 py-2"
disabled={!selectedConstituency}
>
<option value="">Select Ward</option>
{wards.map(ward => (
<option key={ward} value={ward}>
{ward}
</option>
))}
</select>
</div>
{selectedWard && (
<div className="p-4 bg-green-50 border border-green-200 rounded">
<h3 className="font-semibold">Selected Location:</h3>
<p>{selectedWard} Ward, {selectedConstituency}, {selectedCounty}</p>
</div>
)}
</div>
);
}
📊 TypeScript Types
interface County {
county_code: number;
county_name: string;
constituencies: Constituency[];
}
interface Constituency {
constituency_name: string;
wards: string[];
}
interface SearchResult {
county?: County;
constituency?: Constituency;
ward?: string;
}
📖 Data Structure
The package contains hierarchical administrative data:
Kenya (Country)
├── 47 Counties (e.g., Nairobi, Mombasa, Kisumu)
│ ├── 290+ Constituencies (e.g., Westlands, Langata, Dagoretti)
│ │ └── 1,450+ Wards (e.g., Kilimani, Karen, Kangemi)
Example County Structure:
{
"county_code": 47,
"county_name": "Nairobi",
"constituencies": [
{
"constituency_name": "Westlands",
"wards": [
"Kitisuru",
"Parklands/Highridge",
"Karura",
"Kangemi",
"Mountain View"
]
}
]
}
🌍 Data Source & Accuracy
This data is compiled from official sources:
- IEBC (Independent Electoral and Boundaries Commission) - Official electoral boundaries
- KNBS (Kenya National Bureau of Statistics) - Census and statistical data
- OpenStreetMap Kenya - Community-maintained geospatial data
Last Updated: October 2024
Data Version: 1.0.0
Data Accuracy
If you notice any inaccuracies or outdated information, please:
- Open an issue with details
- Provide the official source/reference
- Submit a pull request with corrections
💖 Support This Project
If you find this package useful, please consider supporting its development:
Why Sponsor?
- 🔄 Keep the data updated with latest changes
- 🐛 Faster bug fixes and support
- ✨ New features and improvements
- 📚 Better documentation and examples
- 🌍 Help the Kenyan developer community
Sponsorship Tiers
- ☕ Coffee Supporter ($5/month) - Help keep the project maintained
- 🥉 Bronze Sponsor ($25/month) - Priority support
- 🥈 Silver Sponsor ($100/month) - Logo on README
- 🥇 Gold Sponsor ($500/month) - Custom features
🤝 Contributing
Contributions are welcome! Please see CONTRIBUTING.md for details.
Ways to Contribute
- 🐛 Report bugs
- 💡 Suggest new features
- 📝 Improve documentation
- 🔧 Submit pull requests
- 📊 Update data if you find inaccuracies
- ⭐ Star the repository
- 🔀 Share with others
📝 License
MIT © its-kios09
See LICENSE for full details.
🙏 Acknowledgments
- IEBC for official boundary data
- KNBS for statistical information
- OpenStreetMap Kenya community
- All contributors and supporters
📞 Support & Contact
- 📖 Documentation
- 💬 Discussions
- 🐛 Issue Tracker
🔗 Related Projects
- Kenya GeoJSON - GeoJSON boundaries for mapping
- Kenya Open Data - Open data portal
📈 Stats
Made with ❤️ for the Kenyan developer community
Keywords
kenya osm openstreetmap boundaries counties constituencies wards administrative geography geospatial africa typescript javascript open-source mapping gis location-data