Get the Lat/Lon Location of Major US Cities

Published: January 27th, 2009 by:

In this article, learn how to fetch the latitude & longitude location of all major US cities. I'm going to provide you with a comprehensive list of almost 500 major US cities as well as the source, so you can get the updated list as city sizes change.


This data is provided by the National Digital Forecast Database (NDFD). They supply the city data in groups, or all at once, so you won’t be making calls to this service often, as city locations don’t normally change. As a result, you can skip the task of writing XML parsing and import scripts, and just import the data directly from here. I have prepared a SQL import file straight from this data with no alterations.

City Location Data: SQL | CSV

This data is retrieved by calling the LatLonListCityNames() function from the NDFD. The National Weather Service presents the cities in 4 different levels. More information can be found by viewing their NDFD page and scroll down to the the section that describes the LatLonListCityNames() function.

Example: Query the Database for a City Name

The following code is the best way to find the closest city for the lat/lon provided.

Run This Example

<?php

/**
 * This is how I connect to my database - adjust as necessary
 */
include('../includes/database.php');
$db_link = db_connect();

function get_city_names($lat, $lon, $count = 1)
{
	global $db_link;
	$lat = (float)$lat;
	$lon = (float)$lon;
	
	/**
	 * this query does all the work - with a little math, 
	 * we can search by cloest results
	 */
	$query = "SELECT *, SQRT(POW(69.1 * (lat - $lat), 2) + POW(69.1 * 
		($lon - lon) *  COS(lat / 57.3 ), 2 )) AS distance FROM CityNames 
		ORDER BY distance ASC LIMIT $count";
	$result = mysql_query($query, $db_link);
	
	/**
	 * no need for a multi-dimensial array if there is 
	 * only one result
	 */
	if (mysql_num_rows($result) == 1)
	{
		return mysql_fetch_assoc($result);
	}
	else
	{
		$rows = array();
		for ($i = 0, $c = mysql_num_rows($result); $i < $c; $i++)
		{
			$rows[] = mysql_fetch_assoc($result);
		}
	}
	
	return $rows;
}

/**
 * Get the 5 closest cities to the given coordinates
 */
$cities = get_city_names(41.9224, -87.6524, 5);

header('Content-type: text/plain');
var_dump($cities);

/**
 * Why do I comment out my PHP closing tag?  It's actually not needed!
 * See: http://phpstarter.net/2009/01/omit-the-php-closing-tag/
 */

/* ?> */

Example: Fetching the City Names from the NDFD

You do not need to know this if you use the SQL import file offered above. If you want to know how this data was retrieved, here is an example. It requires a copy of NuSOAP, so download yourself a copy if you don’t have it.

<?php

/**
 * Download NuSOAP from the link below and change the require path accordingly
 * http://sourceforge.net/projects/nusoap/
 */
require('../includes/nusoap/nusoap.php');

/**
 * Fetch the list of cities & location from the NDFD
 * 
 * @param int $level the city level to import (http://www.weather.gov/xml/)
 * @return mixed
 */
function import_city_names($level = 1)
{
	$level = (int)$level;
	
	/**
	 * SOAP parameters go here.  We only need to send the city level
	 */
	$parameters = array('displayLevel' => $level);
	
	/**
	 * couple things can go wrong here; the soap request can fail, or we can 
	 * be sent an invalid XML file, which would cause problems
	 */
	try
	{
		$c = new nusoap_client('http://www.weather.gov/forecasts/xml/DWMLgen/wsdl/ndfdXML.wsdl', 'wsdl');
		
		$result = $c->call('LatLonListCityNames', $parameters, '', '', false, true);
		
		$xml = new SimpleXMLElement($c->return['listLatLonOut']);
	}
	catch (Exception $e)
	{
		/* fail! */
		return false;
	}
	
	/**
	 * parse through the XML fields
	 * run var_dump($xml) to see how the XML data fields are formed
	 */
	$city_name_list = explode('|', $xml->cityNameList);
	$lat_lon_list = explode(' ', $xml->latLonList);
	
	$data = array();
	for ($i = 0, $c = count($city_name_list); $i < $c; $i++)
	{
		$row = array();
		list($row['city'], $row['state']) = explode(',', array_pop($city_name_list));
		list($row['lat'], $row['lon']) = explode(',', array_pop($lat_lon_list));
		
		$data[] = $row;
	}
	
	return $data;
}

/* run the function to list all level 1 cities */
$cities = import_city_names(1);

/**
 * For demonstration purposes, we are just going to dump the data.
 * If this were a production script, we would be putting it in storage (database, etc)
 */
var_dump($cities);

/**
 * Why do I comment out my PHP closing tag?  It's actually not needed!
 * See: http://phpstarter.net/2009/01/omit-the-php-closing-tag/
 */

/* ?> */

Do not use this function every time you need to lookup a city. This information is rarely updated, so it’s best to load it into a database or flat file for storage and retrieval as necessary.

I used this source to search for a weather forecast by city. This data isn’t perfect as it doesn’t cover every town and village, but it covers enough for my purposes. If you know of a free data source that gets more specific, please share in a comment.


Leave a Reply





Wordpress doesn't like it when you post PHP code. Go save your code at pastebin, and post the link here.

About the Author

Andrew has been coding PHP applications since 2006, and has plenty of experience with PHP, MySQL, and Apache. He prefers Ubuntu Linux on his desktop and has plenty of experience at managing CentOS web servers. He is the owner of Wells IT Solutions LLC, and develops PHP applications full time for anyone that needs it as well as does desktop computer support locally in the local area. He spends most of his free time exploring new programming concepts and posting on The Webmaster Forums.