Project Coordinates Safely with PROJ's proj Command
By the end of this guide, you will be able to turn longitude and latitude into projected x and y coordinates, reverse that conversion, and check the numbers before using them in a script or data pipeline. The examples use the proj-bin package version 9.4.0 installed on Ubuntu, with the command-line interface documented by the local PROJ 9.4 manpage. Allow about 10 minutes if PROJ is already installed.
The route
Jump straight to the step you need, or tick off Done means at the end.
Before you start
You need a shell, the proj command, and coordinates whose reference system you understand. Check the installation and version first:
command -v proj
proj --version
dpkg-query -W -f='${Package} ${Version}\n' proj-bin
On this system the relevant output is Rel. 9.4.0, March 1st, 2024 and proj-bin 9.4.0-1build2. Your distribution may package a different release, so keep the local manpage nearby when behaviour differs.
Checkpoint
Continue only when proj resolves to the intended installation. No example in this guide needs elevated privileges.
1. Choose the conversion and coordinate order
proj performs a forward conversion from geographic longitude and latitude to cartesian projected coordinates. The ordinary ASCII input format is two whitespace-separated values in the first two fields. If the line has more fields, trailing text is copied to the output when both input and output are ASCII.
For a forward conversion, write longitude first and latitude second. The following point is longitude 0 degrees, latitude 51 degrees, passed to UTM zone 30 on the WGS84 ellipsoid:
printf '%s\n' '0 51' | proj +proj=utm +zone=30 +ellps=WGS84
The output is:
710488.86 5654109.18
The first value is easting and the second is northing. The default forward format prints two decimal places. UTM coordinates are measured in metres here because the ellipsoid and projection parameters use metre-based units.
The +proj and other +opt arguments describe the cartographic operation. The local manpage also accepts a projected CRS identifier, which is often easier to audit when you already know the EPSG code:
printf '%s\n' '0 51' | proj EPSG:32630 -f '%.3f'
That produces 710488.857 5654109.179, the same result with three decimal places. EPSG:32630 is WGS84 / UTM zone 30N. Do not replace a known source or target CRS with a convenient-looking code: the projection can run successfully while the result is still wrong for your data.
2. Make precision and input visible
Use -f with a printf-style format when a stable number of decimal places matters. For example:
printf '%s\n' '0 51' | proj +proj=utm +zone=30 +ellps=WGS84 -f '%.3f'
For a quick audit, -E copies the input coordinates before the converted values. -d 2 rounds the output to two decimal places:
printf '%s\n' '0 51' | proj +proj=utm +zone=30 +ellps=WGS84 -E -d 2
0 51 710488.86 5654109.18
This is useful when processing a stream because each output row retains an obvious link to its input. The -d option is available from version 5.2.0 onwards. Formatting changes what you see, not the internal coordinate calculation.
Checkpoint
Compare one known point by hand or against a trusted GIS tool. Confirm that the input order, hemisphere, zone, ellipsoid and output units all match your data specification.
3. Reverse a projected coordinate
Use -I for the inverse operation. Feed it the projected x and y values in the same projection definition:
printf '%s\n' '710488.857 5654109.179' | proj -I +proj=utm +zone=30 +ellps=WGS84 -f '%.6f'
The result is:
-0.000000 51.000000
Inverse output is longitude and latitude. The manpage says that inverse output is normally formatted as degrees, minutes and seconds, while -f requests decimal-degree output. The separate invproj command is an alias-style interface for the same inverse mode:
printf '%s\n' '710488.857 5654109.179' | invproj +proj=utm +zone=30 +ellps=WGS84 -f '%.6f'
On platforms where invproj is not available, use proj -I. Keep the projection parameters identical between the two directions. A different zone or ellipsoid can still produce plausible-looking longitude and latitude, which makes this error easy to miss.
4. Handle latitude-first input deliberately
Some files store latitude before longitude. The -r option reverses the expected input order. It affects how input is read, so use it only when the file format says that the first field is latitude:
printf '%s\n' '51 0' | proj +proj=utm +zone=30 +ellps=WGS84 -r -f '%.3f'
The result should match the earlier forward conversion, apart from formatting. The -s option reverses the output order instead. These switches are easy to confuse: -r changes input interpretation, while -s changes output order. Prefer explicit field names in a pipeline and test both a northern and a southern point when the source format is not under your control.
5. Inspect a result without changing data
For a detailed diagnostic, -V prints an annotated listing and implies -v. It is a useful check for the projection parameters, ellipsoid, input interpretation and scale information:
printf '%s\n' '-120 35.8' | proj EPSG:6421 -V
The local manpage's example identifies EPSG:6421 as NAD83(2011) / California zone 4 and shows the selected Lambert Conformal Conic parameters, ellipsoid details, projected coordinates and distortion measures. Treat this output as a diagnostic record, not as a stable machine-readable format. For a short inventory of available projection names, use:
proj -l=merc
That lists the Mercator projection identifier and its defining parameters. The related -lp, -lP, -le and -lu options list projection identifiers, expanded projection descriptions, ellipsoids and distance units respectively.
Common traps and recovery
- Wrong order: longitude and latitude are expected by default. Use
-ronly for a latitude-first source, and use-sonly when the output consumer needs reversed fields. - Wrong reference system:
projis limited to geographic and projected conversion within one datum. Usecs2cswhen you need a transformation between different coordinate reference systems, including datum translation. - Unexpected text: lines beginning with
#are control lines by default and can pass through without processing. Use-tif your input uses another control-line character. - Silent-looking bad data: use
-E,-V, a known test point and explicit formatting before processing a large file. Redirect output to a new file until the sample is verified; this keeps the original data recoverable. - Failed conversion: the default error marker is an asterisk followed by a tab. Use
-e 'ERROR'when a downstream script needs a recognisable error string, and check the command's exit status as well.
Done means
- You identified the installed PROJ version and confirmed which
projbinary is being used. - You converted a known longitude and latitude with an explicit projection and ellipsoid.
- You reversed the result with the same parameters and recovered the original point.
- You checked coordinate order, units, precision and output before using a larger file.
- You know when to use
cs2csinstead ofprojfor datum or CRS-to-CRS work.