Geolocation is where most EUDR projects stall. Not because the rule is complicated, but because the data coming from farms is messy, and the rule leaves no room for messy.
This is the practical version, from the engineering side.
The rule, plainly
For every plot of land that produced the commodity, you need its geolocation:
| Plot | What you provide |
|---|---|
| 4 hectares or less | A single point (latitude, longitude) is allowed |
| More than 4 hectares | A polygon describing the plot boundary |
| Cattle | The establishments where the cattle were kept, not plot polygons in the same sense |
Coordinates need at least six decimal digits. Six decimals is roughly 10 cm at the equator, which is far more precise than most phone GPS readings. That precision requirement is about format, not about pretending your data is accurate to 10 cm.
GeoJSON, the boring way
The EU system takes GeoJSON. The rules that bite people:
- Longitude first. GeoJSON is
[lon, lat], the opposite of how people say coordinates out loud. Half the "plots in the ocean" bugs I have seen come from this. - WGS 84 only. EPSG:4326. If a surveyor gave you UTM coordinates, reproject before export.
- Closed rings. The first and last coordinate of a polygon ring must be identical.
- No self-intersections. A boundary that crosses itself (a "bow tie") is invalid.
- Right-hand rule. RFC 7946 says exterior rings are counter-clockwise. Many tools accept both orientations; validators may not.
A valid small plot as a point:
{ "type": "Feature", "properties": { "plotId": "PLT-0001", "areaHa": 1.8 }, "geometry": { "type": "Point", "coordinates": [36.821946, -1.292066] } }
A valid larger plot as a polygon:
{ "type": "Feature", "properties": { "plotId": "PLT-0002", "areaHa": 6.4 }, "geometry": { "type": "Polygon", "coordinates": [[ [36.820000, -1.290000], [36.823000, -1.290000], [36.823000, -1.293000], [36.820000, -1.293000], [36.820000, -1.290000] ]] } }
You can paste either into my JSON Formatter to check the structure before running geometry checks.
Where the messy data comes from
From what I've seen on real projects, bad geometry usually has one of these origins:
- Phone walk-arounds. Someone walks the boundary with a GPS app. Signal drift creates spikes and self-intersections.
- Hand-typed coordinates. Swapped lat/lon, missing minus signs, or commas as decimal separators.
- Rounded exports. Spreadsheets trimming coordinates to four decimals.
- Overlapping plots. Two farmers claiming the same land, or one plot entered twice.
A validation pipeline that works
I validate in this order, because each step assumes the previous one passed:
Parse
Is it valid JSON, and valid GeoJSON (correct
type,coordinatesnesting)?Sanity-check coordinates
Longitude between -180 and 180, latitude between -90 and 90, at least six decimals, and the point falls inside the declared country of production.
Check geometry
Rings closed, no self-intersections, at least four positions per ring. Libraries like Turf.js (
booleanValidvia helper packages) or Shapely'sis_validdo this.Check the area rule
Compute the area. If it is over 4 hectares and you only have a point, flag it.
Check overlaps
Plots from different producers that overlap heavily usually mean a data entry error.
I go deeper on the code in How to Validate GeoJSON Plot Data Before Submission.
Storing it
Store geometry in a real spatial type, not as a text blob. PostgreSQL with PostGIS gives you validity checks, area calculation, and spatial indexes in the database. I covered the setup in PostGIS for Developers.