# CSV to GeoJSON converter

> Convert a CSV, TSV or Excel file with latitude and longitude columns to a GeoJSON FeatureCollection. See it on a map first. Free, and no account needed.

Open the tool: https://spatibase.com/tools/csv-to-geojson/

The Spatibase CSV to GeoJSON converter turns CSV, TSV and Excel (.xlsx) files into a GeoJSON FeatureCollection of points, in your web browser. It’s free with no account, and your file is never uploaded.

How it reads your file:

- **Detects the layout.** The delimiter (comma, semicolon or tab), the latitude and longitude columns, and decimal commas.
- **Keeps types.** Numbers become JSON numbers, yes/no columns become booleans, and codes with leading zeros such as `08001` stay text.
- **Standard output.** RFC 7946: WGS 84, longitude before latitude.
- **Skipped rows explained.** Rows without usable coordinates are listed with the reason.
- **Limits.** Files up to 50 MB and 50,000 rows.

## What it does
- Convert CSV, TSV and TXT to GeoJSON
- Convert Excel (.xlsx) to GeoJSON
- Detects the delimiter and the latitude and longitude columns
- Keeps numbers, booleans and leading-zero codes as the right JSON types
- Lists the rows without usable coordinates, with the reason
- Also downloads KML and CSV with WKT
- Runs in the browser: nothing is uploaded

## How to convert CSV to GeoJSON
1. Drop a .csv, .tsv, .txt or .xlsx file on the box above, or press Choose a file. The first row must hold the column names. To see the expected layout, download the sample file and open it.
2. Check the map and the notes under it: which columns were used for latitude and longitude, and which rows were skipped and why.
3. Download the GeoJSON, or copy it to paste into your code or geojson.io.
4. Need it for Google Earth or a GIS app instead? Download KML.

## Formats and limits
- **Opens:** .csv, .tsv, .txt (comma, semicolon or tab; UTF-8 or Windows-1252) and .xlsx (the first sheet with data), up to 50 MB and 50,000 rows. Old .xls, .numbers and .ods files: save them as .xlsx or CSV first.
- **Needs:** a header row, a latitude and a longitude column in decimal degrees (WGS 84). No geocoding, no reprojection.
- **Outputs:** GeoJSON (RFC 7946 FeatureCollection of points), KML, CSV with WKT.
- Rows without usable coordinates (empty, not a number, out of range, likely swapped) are listed with the reason.
- Try it with a sample: https://spatibase.com/tools/csv-to-geojson/?sample=1
- Download the sample file (the one Open a sample opens): https://spatibase.com/tools/samples/barcelona.csv

## What does the GeoJSON look like?
The file is a standard GeoJSON FeatureCollection:

- **One Feature per row.** Each row becomes a GeoJSON Feature: a `Point` geometry from the latitude and longitude columns, and every other column as a property. The coordinate columns themselves are not repeated in the properties.
- **RFC 7946, longitude first.** Coordinates are in WGS 84 (the latitude and longitude GPS and web maps use), in the order `[longitude, latitude]`. That order is the most common GeoJSON mistake, so check it if you write the file yourself.

**Types are kept per column.** Each column gets one JSON type:

- **Numbers.** A column of numbers becomes JSON numbers.
- **Booleans.** A column that holds only yes/no or true/false becomes `true` and `false`.
- **Strings.** Anything else, including values that look like numbers but aren’t: postcodes with a leading zero (`08001`) and long ID numbers.
- **Empty cells.** Left out of the properties instead of becoming empty strings.

```json
{
  "type": "FeatureCollection",
  "features": [{
    "type": "Feature",
    "geometry": { "type": "Point", "coordinates": [2.183801, 41.385831] },
    "properties": { "name": "Mercat del Born" }
  }]
}
```

## Convert CSV to GeoJSON in JavaScript
The converter reads CSV with papaparse, the open-source CSV parser. These lines do the core of the job in your own code, in a browser or in Node.js.

```js
import Papa from 'papaparse'

// csv: the file's text, e.g. await file.text() for a File from <input type="file">
const { data } = Papa.parse(csv, { header: true, dynamicTyping: true })
const usable = (n, max) => typeof n === 'number' && Math.abs(n) <= max
const geojson = {
  type: 'FeatureCollection',
  features: data
    .filter((row) => usable(row.latitude, 90) && usable(row.longitude, 180))
    .map(({ latitude, longitude, ...properties }) => ({
      type: 'Feature',
      geometry: { type: 'Point', coordinates: [longitude, latitude] }, // longitude first
      properties,
    })),
}
```

**A papaparse trap.** `dynamicTyping` turns every number-like cell into a number, so a postcode like `08001` becomes `8001`, and it doesn’t read decimal commas (`41,40`). The converter on this page decides per column instead, and reads decimal commas in coordinates.

## Frequently asked questions
### Is my file uploaded?
No. The file is read by your browser, on your computer. Nothing is sent to Spatibase or anyone else. Only the map background (the streets and labels) is loaded from the internet.

### Which columns are used for latitude and longitude?
The converter looks for headers named latitude, lat or y and longitude, lng, lon, long or x, in any case, and a few other languages (latitud, breite). The notes under the map say which two columns it used. Coordinates must be decimal degrees: 41.4036 or 41,4036, not 41°24′13″N.

### Does it convert Excel (.xlsx) to GeoJSON?
Yes. It reads the first sheet that has data and says which one. Numbers, true/false cells and dates in date formats come through as numbers, booleans and ISO dates (2024-05-01). Old .xls files and Numbers or LibreOffice files need to be saved as .xlsx or CSV first.

### Are numbers and true/false values kept as types?
Yes. A column of numbers becomes JSON numbers and a column with only yes/no or true/false values becomes booleans. Postcodes and IDs with leading zeros stay strings, so 08001 doesn’t turn into 8001. Empty cells are left out.

### What about semicolons and decimal commas from European Excel?
Both work. The converter detects comma, semicolon and tab delimiters, and reads coordinates written with a decimal comma (41,4036). Files saved in an older Windows encoding (Windows-1252) are read too, so accents come through.

### My coordinates are in UTM or another projection. Will it work?
No. GeoJSON uses longitude and latitude in WGS 84, and the converter doesn’t reproject. Values in metres are out of range, so those rows are skipped with a note. Convert them to WGS 84 first, for example in QGIS.

## Next step
Serve the data from an API instead of a file: **Save to Spatibase (free)** on the page saves the points to a free Spatibase project (https://app.spatibase.com/signup), on a map your team can edit and with a live GeoJSON address for your site. Or import it by hand: the CSV itself (CSV and TSV, up to 10,000 rows) or the GeoJSON you converted from Excel (https://spatibase.com/docs/content/import/). Published entries come back as GeoJSON and vector tiles from the Content Delivery API.
