online / endpoints 59 / categories 14 / rate 60/min/ip /

GET /geojson

GET /geojson

Returns GeoJSON documents with RFC 7946 violations. Default returns a Polygon whose ring does not close. Use ?mode= to isolate other violations: lat/lon axis swap, type/coordinates mismatch, or absent `properties` member.

mode polygon-not-closed (default; Polygon ring last position differs from first; RFC 7946 §3.1.6 requires an identical closing position; strict validators reject, lenient renderers auto-close silently), coordinates-swapped (coordinates are in [latitude, longitude] order instead of GeoJSON's required [longitude, latitude]; geometry is syntactically valid so parsers accept it and place the point in the wrong hemisphere), type-coords-mismatch (`type` is "Point" but `coordinates` is an array of rings; strict validators reject, lenient renderers produce NaN coordinates), properties-missing (`properties` member absent from the Feature; RFC 7946 §3.2 requires it even if null; libraries that access feature.properties.name throw).

control Compare against the well-formed counterpart: not.catastrophic.io/geojson side-by-side

build a request:

expect: A GeoJSON Feature with one RFC 7946 violation, served as application/geo+json. The `properties.note` or `note` field explains what is wrong.

bash
curl -si 'https://chaos.catastrophic.io/geojson?mode=polygon-not-closed' | grep -E '^(HTTP|content-type|x-chaos)'
import urllib.request, json
resp = urllib.request.urlopen("https://chaos.catastrophic.io/geojson?mode=polygon-not-closed")
print("Content-Type:", resp.headers.get("Content-Type"))
print("X-Chaos-Geojson-Mode:", resp.headers.get("X-Chaos-Geojson-Mode"))
body = json.loads(resp.read())
geom = body.get("geometry", {})
coords = geom.get("coordinates", [])
if geom.get("type") == "Polygon" and coords:
    ring = coords[0]
    print("ring closed:", ring[0] == ring[-1] if ring else "n/a")
print("properties present:", "properties" in body)
print("note:", body.get("note") or body.get("properties", {}).get("note"))
const res = await fetch("https://chaos.catastrophic.io/geojson?mode=polygon-not-closed");
const body = await res.json();
console.log("Content-Type:", res.headers.get("content-type"));
console.log("X-Chaos-Geojson-Mode:", res.headers.get("x-chaos-geojson-mode"));
const geom = body.geometry;
if (geom?.type === "Polygon") {
  const ring = geom.coordinates[0];
  const closed = JSON.stringify(ring[0]) === JSON.stringify(ring.at(-1));
  console.log("ring closed:", closed);
}
console.log("properties present:", "properties" in body);
console.log("geometry type:", geom?.type);
console.log("coordinates type:", Array.isArray(geom?.coordinates[0]) ? "array of rings" : "position");
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    resp, _ := http.Get("https://chaos.catastrophic.io/geojson?mode=polygon-not-closed")
    defer resp.Body.Close()
    raw, _ := io.ReadAll(resp.Body)
    var body map[string]any
    json.Unmarshal(raw, &body)
    fmt.Println("Content-Type:", resp.Header.Get("Content-Type"))
    fmt.Println("X-Chaos-Geojson-Mode:", resp.Header.Get("X-Chaos-Geojson-Mode"))
    _, hasProps := body["properties"]
    fmt.Println("properties present:", hasProps)
    if geom, ok := body["geometry"].(map[string]any); ok {
        fmt.Println("geometry type:", geom["type"])
    }
}
// Cargo.toml: reqwest = { version = "0.12", features = ["blocking", "json"] }
fn main() -> Result<(), Box> {
    let resp = reqwest::blocking::get("https://chaos.catastrophic.io/geojson?mode=polygon-not-closed")?;
    println!("Content-Type: {:?}", resp.headers().get("content-type"));
    println!("X-Chaos-Geojson-Mode: {:?}", resp.headers().get("x-chaos-geojson-mode"));
    let body: serde_json::Value = resp.json()?;
    println!("properties present: {}", body.get("properties").is_some());
    println!("geometry type: {:?}", body["geometry"].get("type"));
    Ok(())
}
import java.net.URI;
import java.net.http.*;

public class GeoJsonChaos {
    public static void main(String[] args) throws Exception {
        var client = HttpClient.newHttpClient();
        var req = HttpRequest.newBuilder(URI.create("https://chaos.catastrophic.io/geojson?mode=polygon-not-closed")).build();
        var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
        System.out.println("Content-Type: " +
            resp.headers().firstValue("Content-Type").orElse(""));
        System.out.println("X-Chaos-Geojson-Mode: " +
            resp.headers().firstValue("X-Chaos-Geojson-Mode").orElse(""));
        System.out.println("Body: " + resp.body());
    }
}
using var client = new HttpClient();
var resp = await client.GetAsync("https://chaos.catastrophic.io/geojson?mode=polygon-not-closed");
Console.WriteLine($"Content-Type: {resp.Content.Headers.ContentType}");
Console.WriteLine($"X-Chaos-Geojson-Mode: " +
    $"{resp.Headers.GetValues("X-Chaos-Geojson-Mode").FirstOrDefault()}");
var body = await resp.Content.ReadAsStringAsync();
Console.WriteLine($"Body: {body}");
require "net/http"
require "json"
uri = URI("https://chaos.catastrophic.io/geojson?mode=polygon-not-closed")
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |http|
    res = http.get(uri.request_uri)
    puts "Content-Type: #{res['Content-Type']}"
    puts "X-Chaos-Geojson-Mode: #{res['X-Chaos-Geojson-Mode']}"
    body = JSON.parse(res.body)
    puts "properties present: #{body.key?('properties')}"
    geom = body['geometry'] || {}
    puts "geometry type: #{geom['type']}"
    if geom['type'] == 'Polygon'
      ring = geom['coordinates'][0]
      puts "ring closed: #{ring.first == ring.last}"
    end
end
$r = Invoke-RestMethod -Uri 'https://chaos.catastrophic.io/geojson?mode=polygon-not-closed' -ResponseHeadersVariable h
"Content-Type: $($h['Content-Type'])"
"X-Chaos-Geojson-Mode: $($h['X-Chaos-Geojson-Mode'])"
"properties present: $($r.PSObject.Properties['properties'] -ne $null)"
"geometry type: $($r.geometry.type)"