WFS Feature Extractor
Pricing
from $0.35 / 1,000 features
WFS Feature Extractor
Point at ANY classic OGC WFS 2.0/1.1 service (GeoServer, MapServer, deegree, QGIS-Server) behind national & city SDIs. Reads GetCapabilities, pages GetFeature by bbox/CQL, returns flat feature rows (geometry, lon/lat, computed bbox, properties, SRS) from GeoJSON OR GML. Pay per feature.
Pricing
from $0.35 / 1,000 features
Rating
0.0
(0)
Developer
Datamule
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
21 days ago
Last modified
Categories
Share
Point at ANY classic OGC WFS service and get clean, flat feature rows.
This actor is a generic runner for the classic OGC Web Feature Service (WFS)
protocol β versions 2.0.0 and 1.1.0 (with a 1.0.0 courtesy fallback). Classic
WFS is the older, still-ubiquitous XML vector-feature standard: GetCapabilities β
GetFeature. It is distinct from the modern JSON-native "OGC API - Features" β if
your service exposes /collections/{id}/items JSON, use an OGC API Features extractor
instead; this one speaks the classic SERVICE=WFS&REQUEST=GetFeature XML protocol that
tens of thousands of GeoServer, MapServer, deegree, QGIS-Server and MapProxy
deployments (national mapping agencies, city GIS portals, INSPIRE / national SDIs)
still serve.
One actor turns any of them into structured rows β no per-site scraper.
What it does
- Reads GetCapabilities and parses the
FeatureTypeListcatalog (name, title, default CRS, advertised output formats). - Pages GetFeature for each requested (or every advertised) feature type, using
COUNT/STARTINDEXpaging on 2.0.0. - Negotiates the wire format: it prefers a GeoJSON format the type advertises, and falls back to the server-default GML β which it fully parses (GML 3.2 / 3.1.1 / 2.x; Point, LineString, Polygon and Multi* geometries) into the same normalized row shape. The GeoJSON path and the GML path yield identical coordinates.
- Normalizes axis order β the classic WFS/GML trap. GeoJSON is lon/lat by spec;
GML coordinate order depends on the CRS, so for the well-known geographic CRSs
(EPSG:4326 and friends) the parser swaps to lon/lat and flags
geoAxisSwapped: true, while CRS84 and projected CRSs (e.g. EPSG:28992) are kept verbatim. Every row records its declaredsrsso nothing is ambiguous.
Modes
- Discovery β leave Feature type name(s) empty (or turn on List feature types only): the actor emits one row per advertised feature type (name, title, abstract, default CRS, supported output formats). A cheap map of what the service serves.
- Extract β set one or more Feature type name(s) (e.g.
ms:cities,bag:pand) and optionally aBBOX, aCQL_FILTER, an OGC XMLFilter, or an outputsrsName.
Input
| Field | Description |
|---|---|
| WFS service URL (required) | Base URL the service answers GetCapabilities on, e.g. https://demo.mapserver.org/cgi-bin/wfs. Any pre-existing query (?map=β¦) is preserved. |
| Feature type name(s) | One or more type names. Empty β discovery mode. |
| List feature types only | Discovery: list the catalog, fetch no features. |
| WFS version | Preferred version (2.0.0 / 1.1.0 / 1.0.0); auto-negotiated. |
| Bounding box (BBOX) | Spatial filter, e.g. -60,-40,-50,-30,urn:ogc:def:crs:EPSG::4326. |
| CQL filter | GeoServer/MapServer CQL_FILTER, e.g. POPULATION > 1000000. |
| OGC XML filter | Raw <fes:Filter> for the standards-based FILTER param. |
| Output format override | Force an OUTPUTFORMAT token; default auto-negotiates. |
| Output SRS (srsName) | Request features reprojected to a CRS, e.g. EPSG:3857. |
| Max features (total) | Cap across all pages/types. One billable event per feature. |
| Page size | Server-side page size per request. |
| Extra query parameters | Vendor-specific passthrough (JSON object). |
| Bearer token / Extra headers | Optional auth for gated deployments. Never logged. |
Output
One row per feature, with a normalized shape regardless of the source wire format:
{"_endpoint": "https://demo.mapserver.org/cgi-bin/wfs","_wfsVersion": "2.0.0","_outputFormat": "geojson","featureType": "cities","featureId": "cities.8338","geometryType": "Point","longitude": -58.6725,"latitude": -34.5875,"bbox": [-58.6725, -34.5875, -58.6725, -34.5875],"srs": "urn:ogc:def:crs:OGC:1.3:CRS84","geoAxisSwapped": false,"propertyKeys": ["NAME", "POPULATION"],"propertyCount": 2,"geometry": { "type": "Point", "coordinates": [-58.6725, -34.5875] },"properties": { "POPULATION": 12116379, "NAME": "Buenos Aires" },"sourceUrl": "https://demo.mapserver.org/cgi-bin/wfs?SERVICE=WFS&β¦","raw": { }}
Some servers (MapServer, for example) leave feature ids out of their GeoJSON. When a
whole GeoJSON page has no ids, the Actor reads the same page once more as GML and copies
each gml:id into featureId, but only if both pages list the same features in the same
order. That extra read is not billed. If it fails or the pages don't match, featureId
stays empty and the log says so.
Discovery rows carry _outputFormat: "capabilities", title, abstract, defaultCrs
and outputFormats instead.
Resilience
Per-type, like a batch harvester: a feature type that errors (HTTP 4xx/5xx, a timeout,
a WFS ExceptionReport, or an unparseable body) is a skip-with-warning and the run
continues. If a GeoJSON request fails, the type is retried once as server-default GML. A
run where every requested type fails exits non-zero (91) so nothing broken ships. A
reachable type that genuinely has no matching features yields 0 rows and a clean exit β
the actor never fabricates rows.
Pricing
Pay-per-event: one feature charge per emitted row.
Your max run charge is respected: each row is billed as it is written, the Actor checks the remaining budget before every GetFeature page and asks the server only for rows you have paid for (a budget below one row makes no request). If a later page fails, the rows already delivered are kept and the run log reports a partial result.
Example
Extract the three most-populous world cities from the OSGeo MapServer demo:
{"wfsUrl": "https://demo.mapserver.org/cgi-bin/wfs","typeNames": ["cities"],"cqlFilter": "POPULATION > 10000000","maxFeatures": 3}