How to Import WFS Data into PostGIS Using GeoPandas - No ArcGIS Needed
Ever wanted to directly pull vector data from an ArcGIS WFS (Web Feature Service) and store it into your PostgreSQL/PostGIS database? π‘
In this quick tutorial, we’ll walk through how to:
-
Fetch live WFS data from an ArcGIS server using GeoPandas
-
Save that spatial data into a PostgreSQL/PostGIS table
-
Do it all with just a few lines of Python π
Whether you’re building a geospatial ETL pipeline or just testing public WFS endpoints, this guide has your back!
π§ Prerequisites
Before diving in, make sure you have these Python packages installed:
pip install geopandas sqlalchemy psycopg2-binary geoalchemy2
β You’ll also need a running PostgreSQL instance with PostGIS enabled.
π Step 1 – Define Your WFS URL
We will use a public ArcGIS WFS service for this example. Here’s the sample URL:
wfs_url=
"https://sampleserver6.arcgisonline.com/arcgis/services/SampleWorldCities/MapServer/WFSServer?service=WFS&version=1.0.0&request=GetFeature&typeName=cities"
This URL returns GML-based WFS data of world cities. Most ArcGIS WFS services follow this format — just replace typeName
as needed.
π Step 2 – Set Up the PostgreSQL Connection
from sqlalchemy import create_engine
# Replace with your own DB credentials
db_user = "postgres"
db_pass = "*******" # Change this!
db_host = "localhost"
db_port = "5432"
db_name = "db_data"
engine = create_engine(f"postgresql://{db_user}:{db_pass}@{db_host}:{db_port}/{db_name}")
π‘ Tip: Make sure your PostGIS extension is enabled with:
CREATE EXTENSION postgis;
π Step 3 – Fetch WFS Data using GeoPandas
import geopandas as gpd
print("β³ Fetching WFS GML data...")
gdf = gpd.read_file(wfs_url)
print("β
Data fetched:", len(gdf), "records")
GeoPandas supports WFS out-of-the-box using
fiona
in the backend. It can parse GML, GeoJSON, and other OGC-standard formats.
π§± Step 4 – Store Data into PostGIS
Now let’s write the GeoDataFrame into a spatial table in PostgreSQL:
table_name = "cities_arcgis"
print(f"πΎ Saving to table: {table_name}")
gdf.to_postgis(name=table_name, con=engine, if_exists="replace", index=False)
print("π Data saved successfully!")
You can also use:
-
if_exists="append"
– to add new records -
if_exists="fail"
– to avoid overwriting
π§ͺ Final Output Check
Log in to your PostgreSQL DB and run:
SELECT COUNT(*), ST_AsText(geom) FROM cities_arcgis LIMIT 5;
You should see the WFS cities successfully imported as geometry records. π―
π Use Cases
This method is perfect for:
-
Automating data ingestion from ArcGIS WFS layers
-
Building PostGIS pipelines from public geoservices
-
Converting live city data, zoning data, land records, and more into local DBs
π§© Gotchas to Watch For
-
ArcGIS WFS sometimes sends invalid GML geometries — try
.buffer(0)
if needed -
Ensure your database supports
geometry
type and SRID match your WFS data -
WFS requests can timeout for large datasets — test with smaller filters
π Conclusion
With GeoPandas + SQLAlchemy, fetching and storing spatial WFS data becomes smooth and scriptable. This simple pipeline can scale to any WFS service — from cities to zoning boundaries to environmental datasets.
π Full Script Recap
import geopandas as gpd from sqlalchemy import create_engine wfs_url=
"https://sampleserver6.arcgisonline.com/arcgis/services/SampleWorldCities/MapServer/WFSServer?service=WFS&version=1.0.0&request=GetFeature&typeName=cities" db_user = "postgres" db_pass = "**********" db_host = "localhost" db_port = "5432" db_name = "db_data" table_name = "cities_arcgis" engine = create_engine(f"postgresql://{db_user}:{db_pass}@{db_host}:{db_port}/{db_name}") print("β³ Fetching WFS GML data...") gdf = gpd.read_file(wfs_url) print("β Data fetched:", len(gdf), "records") print(f"πΎ Saving to table: {table_name}") gdf.to_postgis(name=table_name, con=engine, if_exists="replace", index=False) print("π Data saved successfully!")
β Frequently Asked Questions (FAQ)
πΈ Q1: What is WFS in GIS?
A: WFS (Web Feature Service) is an OGC standard that provides access to vector spatial data (like points, lines, and polygons) over the web. Unlike WMS, which serves images, WFS allows downloading actual geometry + attribute data.
πΈ Q2: Can GeoPandas read WFS services?
A: Yes! GeoPandas can read WFS services directly gpd.read_file(wfs_url)
as long as the WFS returns valid GML or GeoJSON.
πΈ Q3: Do I need ArcMap or ArcGIS Pro to fetch WFS data?
A: No. This method uses only Python, so no ESRI software is required. It works even for ArcGIS-hosted WFS services, as long as the service is public or accessible.
πΈ Q4: What database is used in this tutorial?
A: We use PostgreSQL with the PostGIS extension enabled. This allows us to store and query spatial data like points, lines, and polygons using SQL.
πΈ Q5: What happens if the WFS has a huge dataset?
A: Large WFS layers may take time or timeout. You can:
-
Use WFS filters (
bbox
,CQL_FILTER
, etc.) -
Download in chunks
-
Test the response size before importing
πΈ Q6: Can I append new data to the existing PostGIS table?
A: Yes, simply set it if_exists="append"
in the A to_postgis()
method to keep old data and add new rows.
πΈ Q7: Does this method preserve spatial geometry?
A: Absolutely. GeoPandas preserves the geometry column geometry
and writes it to PostGIS in the proper spatial format with SRID support.
πΈ Q8: What are some real-world use cases?
-
Syncing real-time city data into PostGIS
-
Downloading open land parcel boundaries for offline analysis
-
Automating updates for urban planning dashboards
Comments
Leave a Reply