Getting the data

Getting RCM forecasts via API requests

You can now request data from our RCM forecasts with API requests, which can be either GET or POST requests. For example, you can get 24 temperature values on the UTC day July 3rd, 2025 at DC from the following GET request. ``` url = "https://runnincloud.com/api?key=abc123&var=TMP@2m_above_ground&time=2025-07-03T00:00:00&num_hours=24&points=38.9072,-77.0369" ``` If you need data from more locations, you can set the parameter `points=lat1,lon1,lat2,lon2,lat3,lon3 ...`. To Make it formal, the request contains the following arguments: * `key`: the api key used to access the data * `var`: the name of the variable, one of `["TMP@2m_above_ground", "RH@2m_above_ground", "UGRD@10m_above_ground", "VGRD@10m_above_ground"] * `time`: the forecast’s valid time, given in whole hours (e.g., the hour the forecast applies to) * `num_hours`: total hours of data to return, starting from `time` * `points`: a list of float values representing latitude–longitude pairs in sequence, e.g., lat1,lon1,lat2,lon2,lat3,lon3. Must be given if bbox (below) is absent. * `bbox`: a list of four float values [min_lat, min_lon, max_lat, max_lon] representing the two opposite corners of the bounding box. Must be given if points (above) is absent. Note that the bounding box is drawn in the HRRR map projection, not in the lat/lon coordinate system. * `compress_data`: optional flag to request compressed output. Useful when raw JSON data may exceed 6 MB. The presence of this parameter enables compression, regardless of its value (even if set to false). The dataset covers an area approximately bounded by `lat_min=33.6620, lon_min=-92.4553, lat_max=48.2962, lon_max=-68.4942`. Requests may return an error if a point lies far outside this region or if the specified bbox is entirely outside it. Data is available starting from 2025-06-16T10:00:00 (UTC) and is updated daily at 12:15:00 UTC (08:15:00 Eastern) to include forecasts for the following day. POST allow more data in one request. Below is an example. You will need to first define a payload, which is a dict specifying the data request. You can certainly use `points` instead of `bbox` in your payload ``` bbox_payload = { "key": "abc123", "compress_data": "", # set the compression flag "var": "TMP@2m_above_ground", "time": "2025-07-03T10:00:00", "num_hours": 2, "bbox": "35.000,280.000,35.100,280.100" } ``` Then you can send a post request with the payload. ``` import json import requests def request_data(payload): url = "https://runnincloud.com/api" headers = { "Content-Type": "application/json" } response = requests.post(url, json=payload, headers=headers) result = json.loads(response.text) if response.status_code != 200 or "error" in result: print(f"Error getting the data. Code: {response.status_code}. Message: {response.text}") return None return response ``` If you get a response without an error, then you can extract the data from the response. If the request uses a list of points, then the returned data has dims `(time, points)`, with the `time` dim corresponding to `num_hours` Depending on whether the data is compressed, you can get the data in two ways specified below. ``` import sys import zlib import base64 import numpy as np def extract_data(response): def decode(comp_str): compressed_bytes = base64.b64decode(comp_str.encode('utf-8')) json_str = zlib.decompress(compressed_bytes).decode('utf-8') data_list = json.loads(json_str) recovered_data = np.array(data_list) return recovered_data #The response size is limited to 6 MB, so large requests must be split into smaller ones. #With compression enabled, a single request can retrieve up to num_hours=3 for the entire forecast area (shape = 450 × 600). print(f"Response size: {(sys.getsizeof(response.text) / 1024 / 1024)}:.3fM") result = json.loads(response.text) if result["data_compressed"]: result["data"] = decode(result["data"]) if "lat" in result: result["lat"] = decode(result["lat"]) result["lon"] = decode(result["lon"]) else: result["data"] = np.array(result["data"]) if "lat" in result: result["lat"] = np.array(result["lat"]) result["lon"] = np.array(result["lon"]) print("Get data with shape: ", result["data"].shape) del result["data_compressed"] return result ``` By the following two lines, you will get the data requested in the payload. ``` response = request_data(bbox_payload) result = extract_data(response) print(result) ``` The extracted data `result` includes additional fields that provide context. In the example below, the forecast model was initialized at init_time. The query time "2025-07-03T10:00:00" is 24 hours after initialization, and the request asks for 2 hours of forecast data starting from that time. The lat and lon arrays give the spatial coordinates of the data points. ``` {'init_time': '2025-07-02T10:00:00', 'lead_time_start': '24 hours', 'num_hours': '2', 'var_name': 'TMP@2m_above_ground', 'unit': 'K', 'data': array(...), 'lat': array(...), 'lon': array(...), 'dims': '(time, y, x)'} ```