← Argo Float Data Explorer

🛰️ Data API

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.

What makes it useful unique

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.

Endpoints

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.

FileWhatRows
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-

Query it

DuckDB: SQL straight over HTTP (nothing to download)

-- 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;

pandas

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"]]

JavaScript / any HTTP client

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)

Schema notes (read these first)

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.

FieldGotcha
last_date
data_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.

Value vocabularies

ColumnValues
data_kindcore (17,432) or bgc (2,913)
is_deeptrue 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)
dacthe Data Assembly Centre: coriolis, aoml, jma, and so on
regionThere 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.

Getting the actual profile data

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.

License & citation

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.