Query the whole Argo array by sensor serial number, model, WMO, float type, or region, straight over HTTP with DuckDB or pandas. Free and no key required. Data © Argo, CC BY 4.0.
The GDAC is a file server; argopy, Argovis, and ERDDAP already do excellent space/time/parameter queries of profile data, so use those for that. What none of them offer is a serial-number / sensor index: going from a physical CTD or optode (its serial, model, or maker) to the float it's on. That's this API's reason to exist.
Base: https://vladsimontov.github.io/ArgoFloatData/api/
· rebuilt daily by CI · served as static files from GitHub Pages, so please be
reasonable with bulk polling.
| File | What | Rows |
|---|---|---|
sensors.parquet |
one row per (float, sensor): WMO, sensor, model, maker, serial no. | 75,480 |
floats.parquet |
one row per float: type, platform, last position, data path (see the schema notes) | 20,345 |
floats.json |
compact per-float index for JS/browser use (each row has a full GDAC data_url) | 20,345 |
index.json |
self-describing manifest: files, schema, counts | - |
-- Which float carries CTD serial 17106?
SELECT wmo, sensor, sensor_model, sensor_maker
FROM 'https://vladsimontov.github.io/ArgoFloatData/api/sensors.parquet'
WHERE sensor_serial_no = '17106';
-- Every float recording an SBE61 (the 6000 m Deep CTD): a lookup no other Argo API
-- offers. Returns 269 floats. NOTE this is "floats whose DAC recorded an SBE61",
-- not "every 6000 m float": 352 floats are 6000 m-capable models, but 88 of them
-- never record the CTD model. For the hull rather than the sensor, use profiler_type
-- on floats.parquet (849 APEX_D, 862 SOLO_D, 874 SOLO_D_MRV, 882 XUANWU).
SELECT DISTINCT wmo, sensor_serial_no
FROM 'https://vladsimontov.github.io/ArgoFloatData/api/sensors.parquet'
WHERE sensor_model = 'SBE61';
-- Floats still reporting: the live array, about 4,300 of the 20,345 indexed.
-- last_date is packed YYYYMMDDHHMMSS, so parse it before comparing (see Schema).
SELECT wmo, data_kind, last_lat, last_lon, last_date
FROM 'https://vladsimontov.github.io/ArgoFloatData/api/floats.parquet'
WHERE strptime(CAST(CAST(last_date AS BIGINT) AS VARCHAR), '%Y%m%d%H%M%S')
> now() - INTERVAL 60 DAY;
-- Find a float by its FLOAT serial (not the sensor's)
SELECT wmo, float_serial_no, platform_type, dac
FROM 'https://vladsimontov.github.io/ArgoFloatData/api/floats.parquet'
WHERE float_serial_no ILIKE '%22EU002%';
-- Region search: every float within 500 km of a point, nearest first. This is exactly
-- what the app's "Mediterranean (western)" preset runs, and returns the same 165 floats.
-- There is no region column: a region is a point plus a radius, or a lat/lon box.
WITH d AS (
SELECT wmo, data_kind, last_lat, last_lon,
6371 * 2 * asin(sqrt(
pow(sin(radians(last_lat - 39.0)/2), 2)
+ cos(radians(39.0)) * cos(radians(last_lat))
* pow(sin(radians(last_lon - 5.0)/2), 2))) AS km
FROM 'https://vladsimontov.github.io/ArgoFloatData/api/floats.parquet'
WHERE last_lat IS NOT NULL AND last_lon IS NOT NULL)
SELECT wmo, data_kind, round(km) AS km FROM d WHERE km <= 500 ORDER BY km;
-- BGC floats in a lat/lon box, with each float's GDAC data file
SELECT wmo, last_lat, last_lon, expected_rel
FROM 'https://vladsimontov.github.io/ArgoFloatData/api/floats.parquet'
WHERE data_kind = 'bgc'
AND last_lat BETWEEN 30 AND 45 AND last_lon BETWEEN -10 AND 40;
import pandas as pd
B = "https://vladsimontov.github.io/ArgoFloatData/api/"
sensors = pd.read_parquet(B + "sensors.parquet")
sensors.query("sensor_model == 'SBE61'")[["wmo", "sensor_serial_no"]]
const floats = await (await fetch(
"https://vladsimontov.github.io/ArgoFloatData/api/floats.json")).json();
const deep = floats.filter(f => f.deep); // each row has f.data_url (GDAC NetCDF)
Three fields behave in ways that will bite you if you assume otherwise. The
self-describing index.json carries the
live counts and column lists.
| Field | Gotcha |
|---|---|
last_datedata_through |
Not a timestamp. It is packed YYYYMMDDHHMMSS
as a number, so 20011005192213 means 2001-10-05 19:22:13. Passing
it to a date parser as if it were an epoch silently yields nonsense rather
than an error. Parse the digits. |
parameters |
Populated for BGC floats only (2,913 of 20,345 rows). It is blank for every core float, which does not mean the float measures nothing: core floats measure PRES, TEMP and PSAL. |
sensor_model |
Only as good as what each DAC recorded. 88 of the 352 6000 m-capable
floats never record their SBE61, so sensor-model filters undercount the
hardware. Cross-check with profiler_type when the hull matters. |
| Column | Values |
|---|---|
data_kind | core (17,432) or bgc (2,913) |
is_deep | true for 587 floats: profiles below 4000 m. Independent of data_kind, so a float can be both BGC and Deep. |
data_suffix | _Sprof.nc (BGC synthetic) or _prof.nc (core/deep) |
dac | the Data Assembly Centre: coriolis, aoml, jma, and so on |
| region | There is no region column. A region is last_lat /
last_lon: either a box, or a radius around a point (see the region
recipe above). The app's 21 region presets are just saved coordinates and radii. |
Every float row points at its NetCDF on the GDAC, but the two fields differ:
floats.json carries data_url, a complete URL you can fetch
as-is; the Parquet files carry expected_rel, a path
relative to a GDAC root such as
https://data-argo.ifremer.fr/, so you must join it onto one. Fetch
that directly, or for gridded
space/time queries use argopy /
ERDDAP / Argovis. This API doesn't
rehost the ~200 GB of profile data; it indexes it.
Argo data are © the International Argo Program under CC BY 4.0. Cite: Argo (2026). Argo float data and metadata from Global Data Assembly Centre (Argo GDAC). SEANOE. https://doi.org/10.17882/42182. The index refreshes daily.