BOEM Offshore Data Skill
Fetches and analyzes federal OCS offshore oil and gas data from the BOEM/BSEE ArcGIS REST MapServer and BOEM Data Center bulk downloads.
API Key Handling
No API key is required. All BOEM and BSEE data services are public and freely accessible without authentication.
Data Sources
BOEM provides two primary access methods:
- ArcGIS REST MapServer — real-time spatial and attribute queries against national and regional GIS layers (wells, platforms, leases, pipelines, boundaries)
- Bulk ASCII Downloads — zipped delimited text files from the BOEM Data Center containing full database exports (production, borehole, lease owner, etc.)
See references/endpoints.md for the complete endpoint catalog.
API Structure
GIS MapServer (Primary Query Interface)
Base URL: https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer
Key Layers:
| Layer ID | Name | Geometry | Approx Records |
|---|---|---|---|
| 0 | OCS Drilling Platforms | Point | ~1,354 |
| 1 | OCS Oil and Natural Gas Wells | Point | ~56,363 |
| 2 | OCS Oil & Gas Pipelines | Polyline | varies |
| 15 | BOEM Oil and Gas Leases | Polygon | ~1,994 |
| 20 | BOEM Oil and Gas Planning Areas | Polygon | — |
Query parameters for {MapServer}/{LayerID}/query:
| Parameter | Example | Notes |
|---|---|---|
| where | where=STATUS='PA' | SQL WHERE clause |
| outFields | outFields=API_NUMBER,OPERATOR,DEPTH | Comma-separated field list |
| geometry | geometry=-91,28,-89,29 | Bounding box xmin,ymin,xmax,ymax |
| geometryType | geometryType=esriGeometryEnvelope | Envelope, Point, Polygon |
| spatialRel | spatialRel=esriSpatialRelIntersects | Spatial relationship |
| resultRecordCount | resultRecordCount=100 | Max rows per request |
| resultOffset | resultOffset=100 | Pagination offset |
| returnCountOnly | returnCountOnly=true | Count without data |
| orderByFields | orderByFields=DEPTH DESC | Sort order |
| f | f=json | Response format (json, geojson) |
Bulk Data Downloads
Base URL: https://www.data.boem.gov/
Key download files (all zip archives of delimited text):
| Data Type | URL Path |
|---|---|
| OGOR-A Production | /Production/Files/ogoradelimit.zip |
| OGOR-A by Year | /Production/Files/ogora{YYYY}delimit.zip |
| OCS Production Summary | /Production/Files/OCSProdRawData.zip |
| Borehole Data | /Well/Files/BoreholeRawData.zip |
| Lease Owner | /Leasing/Files/LeaseOwnerRawData.zip |
| Platform Structures | /Platform/Files/PlatStrucRawData.zip |
| Pipeline Locations | /Pipeline/Files/PipeLocRawData.zip |
| Company Data | /Company/Files/CompanyRawData.zip |
Key Fields by Layer
Wells (Layer 1)
API_NUMBER— 12-digit API well numberOPERATOR— Operator company number (cross-ref with Company data)WELL_NAME— Well name/designationSPUD_DATE— Date drilling commencedTYPE_CODE_DESC— Well type (Development, Exploratory)STATUS/STATUS_DESCRIPTION— Current status (PA=Permanently Abandoned, COM=Completed, DRL=Drilling, etc.)DEPTH— Total depth (feet)X,Y— Longitude, Latitude (NAD83)
Platforms (Layer 0)
COMPLEX_ID_NUM— Platform complex identifierINSTALL_DATE— Installation dateREMOVAL_DATE— Removal date (null = still active)
Leases (Layer 15)
LEASE_NUMBER— OCS lease serial numberLEASE_STATUS_CD— Status (PROD, EXPR, RELD, TERM, SOP, SOO)LEASE_EFF_DATE/LEASE_EXPIR_DATE— Effective and expiration datesSALE_NUMBER— Lease sale numberROYALTY_RATE— Royalty rate (fraction)MINERAL_TYPE_CD— Mineral type codeCURRENT_AREA/INITIAL_AREA— Lease area
Workflow
Step 1 — Resolve Intent
Map the user's question to the appropriate layer and query type:
| User Intent | Layer | Query Type |
|---|---|---|
| Offshore wells, drilling | wells (1) | Attribute/Spatial |
| Platforms, structures | platforms (0) | Attribute/Spatial |
| Lease status, sales | leases (15) | Attribute |
| Pipeline infrastructure | pipelines (2) | Spatial |
| Production volumes, OGOR data | — | Bulk download |
| Planning areas, boundaries | planning (20) | Attribute |
If uncertain which layer to query, start by checking the MapServer root to list available layers:
curl -s "https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer?f=json" \
| jq '.layers[] | {id, name}'
Step 2 — Build the Query
Attribute query (e.g., wells by status):
curl -s "https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer/1/query" \
--data-urlencode "where=STATUS='PA'" \
--data-urlencode "outFields=API_NUMBER,OPERATOR,WELL_NAME,STATUS_DESCRIPTION,DEPTH,TYPE_CODE_DESC,SPUD_DATE" \
--data-urlencode "resultRecordCount=20" \
--data-urlencode "f=json"
Spatial query (e.g., wells within a bounding box):
curl -s "https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer/1/query" \
--data-urlencode "geometry=-91,28,-89,29" \
--data-urlencode "geometryType=esriGeometryEnvelope" \
--data-urlencode "spatialRel=esriSpatialRelIntersects" \
--data-urlencode "outFields=API_NUMBER,OPERATOR,WELL_NAME,STATUS_DESCRIPTION,DEPTH" \
--data-urlencode "resultRecordCount=20" \
--data-urlencode "f=json"
Count query (e.g., how many wells total):
curl -s "https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer/1/query?where=1%3D1&returnCountOnly=true&f=json"
Platform query (active platforms only):
curl -s "https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer/0/query" \
--data-urlencode "where=REMOVAL_DATE IS NULL" \
--data-urlencode "outFields=COMPLEX_ID_NUM,INSTALL_DATE" \
--data-urlencode "resultRecordCount=10" \
--data-urlencode "f=json"
Lease query (producing leases):
curl -s "https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer/15/query" \
--data-urlencode "where=LEASE_STATUS_CD='PROD'" \
--data-urlencode "outFields=LEASE_NUMBER,LEASE_STATUS_CD,LEASE_EFF_DATE,SALE_NUMBER,ROYALTY_RATE" \
--data-urlencode "resultRecordCount=10" \
--data-urlencode "f=json"
Bulk production download:
# Download all OGOR-A production data (pipe-delimited, ~1.3 MB compressed)
curl -sO "https://www.data.boem.gov/Production/Files/ogoradelimit.zip"
# Or a single year
curl -sO "https://www.data.boem.gov/Production/Files/ogora2024delimit.zip"
Step 3 — Parse Response
GIS query responses follow this structure:
{
"displayFieldName": "API_Number",
"fieldAliases": { "API_NUMBER": "API_NUMBER", ... },
"geometryType": "esriGeometryPoint",
"spatialReference": { "wkid": 4269 },
"fields": [ { "name": "API_NUMBER", "type": "esriFieldTypeString", ... } ],
"features": [
{
"attributes": {
"API_NUMBER": "608104006000",
"OPERATOR": "00250",
"WELL_NAME": " 001",
"STATUS_DESCRIPTION": "Permanently Abandoned",
"DEPTH": "12500",
"TYPE_CODE_DESC": "Development"
},
"geometry": { "x": -90.123, "y": 28.456 }
}
]
}
Key parsing notes:
- Feature data is in
features[].attributes - Coordinates are in
features[].geometry(NAD83, lon/lat) - Date fields are millisecond epoch timestamps (divide by 1000 for Unix time)
- The
OPERATORfield is a company number, not a name — cross-reference with Company bulk data for operator names
Step 4 — Produce Output
Format: Raw Data Table + Narrative
Present a markdown table of the most relevant rows (cap at ~20 rows for readability), then a narrative summary covering:
- Current state — count of features, geographic scope
- Key statistics — depth ranges, status breakdowns, temporal coverage
- Geographic context — planning area, water depth zone if applicable
- Data quality notes — operator codes vs names, date format caveats
Example output structure:
## OCS Wells — Central Gulf of Mexico (28-29N, 89-91W)
| API Number | Operator | Well Name | Status | Depth (ft) | Type |
|-----------------|----------|-----------|---------------------|------------|-------------|
| 608104006000 | 00250 | 001 | Permanently Abandoned| 12,500 | Development |
| 608174002101 | 02481 | A001 | Completed | 18,200 | Exploratory |
| ... | ... | ... | ... | ... | ... |
**Summary:** Query returned 247 wells within the bounding box -91,28 to -89,29
in the central Gulf of Mexico. Of these, 68% are permanently abandoned, 22% are
completed, and 10% are in other statuses. Well depths range from 2,100 to
31,400 ft, with a median of 14,800 ft. The area spans portions of the Central
Planning Area (CPA) and includes both shelf and deepwater wells. Operator codes
shown — use the Company bulk download for operator name lookup.
Pagination
The ArcGIS REST API limits results per request (typically 1,000-2,000 features
depending on server configuration). Use resultRecordCount and resultOffset
to paginate:
import json
import urllib.request
import urllib.parse
offset = 0
page_size = 1000
all_features = []
while True:
params = urllib.parse.urlencode({
"where": "1=1",
"outFields": "API_NUMBER,OPERATOR,STATUS",
"resultRecordCount": str(page_size),
"resultOffset": str(offset),
"f": "json",
})
url = f"https://gis.boem.gov/arcgis/rest/services/BOEM_BSEE/MMC_Layers/MapServer/1/query?{params}"
with urllib.request.urlopen(url) as resp:
data = json.loads(resp.read())
features = data.get("features", [])
if not features:
break
all_features.extend(features)
offset += len(features)
if len(features) < page_size:
break
print(f"Total features: {len(all_features)}")
Warn the user if a dataset exceeds ~10,000 features and suggest spatial or attribute filters to narrow results.
Error Handling
| HTTP Code / Condition | Meaning | Action |
|---|---|---|
| 200 + empty features[] | No matching records | Adjust WHERE clause or spatial filter |
| 200 + error in JSON | Invalid query syntax | Check SQL WHERE syntax, field names |
| 400 | Bad request parameters | Verify field names exist on the layer |
| 403 | Access denied | Should not occur (public data) |
| 404 | Layer or service not found | Verify layer ID exists; check service URL |
| 500 | Server error | Retry after brief delay |
| Timeout | Large result set | Add spatial filter or reduce record count |
| Bulk download returns HTML | File URL changed | Check /Main/RawData.aspx for current URLs |
Regional GIS Services
In addition to the national MMC_Layers, BOEM provides regional MapServers with additional detail:
| Region | Service URL |
|---|---|
| Gulf of America | .../BOEM_BSEE/GOA_Layers/MapServer |
| Atlantic | .../BOEM_BSEE/ATL_Layers/MapServer |
| Pacific | .../BOEM_BSEE/POC_Layers/MapServer |
| Alaska | .../BOEM_BSEE/AK_Layers/MapServer |
The GOA (Gulf of America) service includes additional layers such as Seismic Anomalies (layer 9) and Lease Points (layer 11).
OCS Planning Areas Reference
| Code | Area | Region |
|---|---|---|
| CPA | Central Planning Area | Gulf of America |
| WPA | Western Planning Area | Gulf of America |
| EPA | Eastern Planning Area | Gulf of America |
| MDA | Mid-Atlantic | Atlantic |
| SAA | South Atlantic | Atlantic |
| NAA | North Atlantic | Atlantic |
Geo Reference
Coordinate System: All national GIS layers use NAD83 (WKID 4269). Coordinates are geographic (longitude, latitude in decimal degrees).
Key geographic bounding boxes for common queries:
| Area | Bounding Box (xmin,ymin,xmax,ymax) |
|---|---|
| Entire Gulf of Mexico | -98,24,-81,31 |
| Central GOM (deepwater) | -92,26,-87,29 |
| Western GOM | -98,26,-92,30 |
| Eastern GOM | -87,25,-81,30 |
| Southern California | -121,33,-117,35 |
| Cook Inlet, Alaska | -154,59,-149,62 |
Caveats and Data Quality
- Operator codes, not names: The GIS well layer returns numeric operator codes (e.g., "00250"). Cross-reference with the Company bulk download for actual operator names.
- Date formats vary: GIS date fields are millisecond epoch timestamps. The SPUD_DATE field on wells is a string (MM/DD/YYYY). Bulk downloads use various date formats per file.
- GIS vs. official records: Per BOEM notice, GIS layers should not be used for legal or official purposes due to re-projection artifacts. The official records are in BOEM's internal database.
- Production data lag: OGOR-A production data typically lags 2-3 months behind current date. The most recent months may show incomplete volumes.
- Water depth not in GIS: The well GIS layer does not include water depth. For water depth analysis, use the Offshore Statistics bulk download or the borehole raw data files.
- Bulk download availability: Some bulk download URLs change periodically. If a URL returns an HTML page instead of a zip file, check the Raw Data page at https://www.data.boem.gov/Main/RawData.aspx for current links.
Implementation Notes
- Prefer
bash_toolwithcurlfor GIS queries — the REST API returns clean JSON thatjqhandles well - Use
python3for bulk data processing — seereferences/python_example.pyfor a stdlib-only client with pagination, spatial queries, and downloads - Spatial reference: Always NAD83 (WKID 4269) for national layers
- Record limits: Default server limit is ~2,000 features per request;
paginate with
resultOffsetfor larger result sets - GeoJSON output: Add
f=geojsoninstead off=jsonfor GeoJSON-format responses compatible with mapping tools - BOEM Data Center updates: Well and lease data are updated frequently (weekly to monthly). Production data is updated quarterly.