Parse ESRI-flavored WKT (as produced by ArcGIS .prj exports) and convert it to
an EPSG code, standard OGC WKT, or proj4 string.
Only new-style pseudo-OGC WKT (PROJCS[...] / GEOGCS[...]) is supported; the legacy
Arc/Info 7.x key-value .prj format is not.
This library bundles a subset of EPSG entries for matching and 316 datum transforms from PROJ data. It works entirely offline. WKT and proj4 rebuilding works for any parseable ESRI WKT, regardless of whether an EPSG match exists.
npm install esriwkt
import { parseEsriWkt } from "esriwkt";
const wkt =
'PROJCS["ETRS_1989_UTM_Zone_32N",GEOGCS["GCS_ETRS_1989",DATUM["D_ETRS_1989",' +
'SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],' +
'UNIT["Degree",0.0174532925199433]],PROJECTION["Transverse_Mercator"],' +
'PARAMETER["False_Easting",500000.0],PARAMETER["False_Northing",0.0],' +
'PARAMETER["Central_Meridian",9.0],PARAMETER["Scale_Factor",0.9996],' +
'PARAMETER["Latitude_Of_Origin",0.0],UNIT["Meter",1.0]]';
const crs = parseEsriWkt(wkt);
crs.toEpsg(); // 25832
crs.toWkt(); // OGC WKT: PROJCS["ETRS89 / UTM zone 32N",GEOGCS["ETRS89",...AUTHORITY["EPSG","25832"]]
crs.toProj4(); // +proj=utm +zone=32 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs +type=crsparseEsriWkt() returns an EsriWkt object. Each conversion method (toEpsg(),
toWkt(), toProj4()) is lazy and caches its result. The params property exposes
the normalized parameters directly.
Parses an ESRI WKT string. Throws if the WKT cannot be parsed.
| Member | Return type | Description |
|---|---|---|
params |
NormalizedCrsParams |
The normalized parameters extracted from the WKT (angles in radians, distances in meters). |
toEpsg() |
number | null |
Returns the matched EPSG code, or null if no match was found. |
toWkt() |
string | null |
Returns the rebuilt OGC WKT1 string, or null if the projection is unrecognized. |
toProj4() |
string | null |
Returns the rebuilt proj4 string, or null if the projection is unrecognized. |
All three conversion methods are lazy and cache their result, so repeated calls return the same value without re-computation.
- If the WKT has an embedded
AUTHORITY["EPSG", code], that code is returned directly. - If it has an embedded
AUTHORITY["Esri", wkid], a crosswalk table maps known legacy ESRI WKIDs (e.g.102100->3857) to EPSG codes. - Otherwise, the WKT is parsed into normalized parameters (projection method, ellipsoid, origin, false easting/northing, scale factor, etc.) and compared against the bundled dataset within numeric tolerances. Geographic CRSs that share identical ellipsoid parameters (e.g. NAD83, ETRS89, GDA94 all use GRS80) are disambiguated by datum-name similarity.
The parsed parameters are re-serialized using small lookup tables that map ESRI naming conventions to their OGC WKT and proj4 equivalents:
- Projection names: ESRI names like
Lambert_Conformal_Conic-> OGCLambert_Conformal_Conic_2SP/ proj4lcc. - Parameter names: ESRI names like
False_Easting-> OGCfalse_easting/ proj4x_0. - Ellipsoid names: proj4 codes like
GRS80-> OGCGRS 1980. - Datum transforms: 316
+towgs84=entries auto-generated from PROJ data, plus manual entries for grid-based datums like NAD27. - Prime meridians: offsets like 2.337° ->
PRIMEM["Paris",...]/+pm=paris.
Angles are converted from radians (internal) to degrees (output). Linear false easting/northing values are kept in meters for proj4 (per proj4 convention) and converted to the CRS linear unit for WKT. When a datum transform is unknown, the datum-shift clause is omitted rather than guessed.
Non-Greenwich prime meridians are serialized as PRIMEM["Paris",...] in WKT and
+pm=paris in proj4. EXTENSION["PROJ4_GRIDS",...] clauses from the source WKT are
preserved and preferred over the built-in nadgrids value. Oblique Mercator (RSO)
projections emit +gamma= for the rectified grid angle and +no_uoff in proj4.
Mercator 1SP vs 2SP is distinguished by the presence of a non-zero standard parallel.
When no EPSG match is found, projected CRS names are canonicalized from ESRI naming
patterns (e.g. WGS_1984_UTM_Zone_33S -> WGS 84 / UTM zone 33S).
toEpsg() can only return codes for CRSs in the bundled dataset (or those carrying
an embedded AUTHORITY clause). The dataset is a small curated subset, so some CRSs
may not resolve to an EPSG code even though toWkt() and toProj4() will still
produce output.
The library includes 316 +towgs84= datum transforms auto-generated from PROJ
data, plus a handful of grid-based (+nadgrids=) entries for common datums like
NAD27. Datums that require a grid file for accurate transformation (e.g. OSGB36
with OSTN15, NAD83 CSRS) will produce valid proj4 output but without the grid
reference, so datum transformation may be less accurate.
Only WKT1 (PROJCS[...] / GEOGCS[...]) is produced. The newer WKT2 format
(PROJCRS[...] / GEODCRS[...]) is not supported.
Some datums have multiple regional transforms to WGS84 (e.g. ED50 has 38 variants for different countries). The library picks a single general-purpose transform for each datum. This is accurate to a few metres but not optimal for a specific region.
The library uses a chain of optional NTv2 grid files (@ntv2_0.gsb,@conus,@alaska),
while epsg.io uses a single grid file. Both are valid, but the output may not match
epsg.io exactly for NAD27-based CRSs.
When toEpsg() cannot find a match, toWkt() attempts to derive a canonical name
from the ESRI naming pattern (e.g. WGS_1984_UTM_Zone_33S becomes
WGS 84 / UTM zone 33S). Complex or non-standard names will pass through unchanged.
Ten prime meridians are recognized (Greenwich, Paris, Madrid, Lisbon, Rome, Jakarta, Bern, Stockholm, Athens, Oslo). Unrecognized meridians are emitted with a numeric offset from Greenwich rather than a named reference.