How to Use HTTP POST with the Visual Crossing Weather API

Most Visual Crossing Weather API requests can be made using a standard HTTP GET request. In some applications, however, HTTP POST is a better choice, particularly when the request contains a large number of parameters or a long list of locations.

The Visual Crossing Timeline Weather API supports supplying its additional request parameters using either GET query parameters or POST form data. The weather data returned by the API is the same regardless of which method you use.

In this article, we’ll look at:

  • The difference between GET and POST requests
  • When to use POST with the Weather API
  • How to make a POST request using cURL
  • How to make a POST request using Python
  • How to make a POST request using JavaScript
  • How POST is particularly useful with the multiple-location Timeline API
  • Security, usage, and request-size considerations

GET versus POST Weather API requests

A typical HTTP GET request places the request parameters in the URL.

For example:

https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/London,UK/2026-08-01/2026-08-07?unitGroup=metric&include=days&key=YOUR_API_KEY

This is simple to create, easy to test in a browser, and appropriate for most Weather API requests.

With HTTP POST, additional request parameters can instead be placed in the HTTP request body.

For example, the URL can contain the main Timeline path:

https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/London,UK/2026-08-01/2026-08-07

while parameters such as the API key, unit group, and requested data sections are included in the POST body:

key=YOUR_API_KEY
unitGroup=metric
include=days

The Timeline Weather API documentation identifies these additional parameters as Query or POST Parameters, meaning they can be supplied either in the URL query string or as part of a POST request.

When should I use HTTP POST?

For most single-location Timeline Weather API requests, GET is the simplest option and is generally recommended.

POST becomes useful when:

  • The complete GET URL becomes very long.
  • You are submitting a large list of locations using the multiple-location Timeline endpoint.
  • Your application or HTTP framework is designed around form-based POST requests.
  • You prefer to keep request parameters separate from the URL.
  • You want to reduce the chance that parameters will appear in URL histories, URL logs, analytics systems, or copied links.

There is no single universal maximum URL length that applies to every browser, HTTP client, proxy, gateway, or server. Long URLs can therefore cause compatibility problems even if they work correctly in one environment.

POST moves parameters from the URL into the request body and avoids many of these URL-length concerns.

HTTP request bodies are not unlimited either, so applications should still avoid unnecessarily large requests.

Timeline path parameters and POST parameters

The standard Timeline Weather API uses the following URL structure:

/timeline/[location]/[date1]/[date2]

For example:

/timeline/London,UK/2026-08-01/2026-08-07

The location and dates form the primary request path.

Additional options such as:

key
unitGroup
include
elements
lang
contentType
options

can be supplied as query or POST parameters.

This means that changing a Timeline request from GET to POST does not require changing the basic Timeline endpoint.

Making a POST Weather API request with cURL

cURL is a convenient way to test HTTP POST requests from a command line.

For example, the following request retrieves daily weather data for London from August 1 through August 7, 2026:

curl -X POST \
  "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/London,UK/2026-08-01/2026-08-07" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "key=YOUR_API_KEY" \
  --data-urlencode "unitGroup=metric" \
  --data-urlencode "include=days" \
  --data-urlencode "contentType=json"

The --data-urlencode option tells cURL to place each value into a URL-encoded POST request body.

The equivalent GET request would be:

https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/London,UK/2026-08-01/2026-08-07?key=YOUR_API_KEY&unitGroup=metric&include=days&contentType=json

Both requests retrieve the same weather information.

Requesting only specific weather elements

You can also include the elements parameter in the POST request.

For example:

curl -X POST \
  "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timeline/London,UK/2026-08-01/2026-08-07" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "key=YOUR_API_KEY" \
  --data-urlencode "unitGroup=metric" \
  --data-urlencode "include=days" \
  --data-urlencode "elements=datetime,tempmax,tempmin,precip,conditions" \
  --data-urlencode "contentType=json"

This limits the response to the fields needed by the application and can reduce the amount of data transferred.

Making a POST Weather API request in Python

Python’s standard library can make an HTTP POST request without requiring any additional packages.

from urllib.parse import urlencode
from urllib.request import Request, urlopen

url = (
    "https://weather.visualcrossing.com/"
    "VisualCrossingWebServices/rest/services/timeline/"
    "London,UK/2026-08-01/2026-08-07"
)

params = {
    "key": "YOUR_API_KEY",
    "unitGroup": "metric",
    "include": "days",
    "elements": "datetime,tempmax,tempmin,precip,conditions",
    "contentType": "json"
}

body = urlencode(params).encode("utf-8")

request = Request(
    url,
    data=body,
    headers={
        "Content-Type": "application/x-www-form-urlencoded"
    },
    method="POST"
)

with urlopen(request) as response:
    weather_json = response.read().decode("utf-8")

print(weather_json)

The params dictionary contains the same parameters that would normally appear after the ? in a GET request.

urlencode() converts them into the standard form-encoded POST format before the request is sent.

Using the Requests package

If your Python application already uses the popular requests package, the same operation is even simpler:

import requests

url = (
    "https://weather.visualcrossing.com/"
    "VisualCrossingWebServices/rest/services/timeline/"
    "London,UK/2026-08-01/2026-08-07"
)

params = {
    "key": "YOUR_API_KEY",
    "unitGroup": "metric",
    "include": "days",
    "elements": "datetime,tempmax,tempmin,precip,conditions",
    "contentType": "json"
}

response = requests.post(url, data=params)
response.raise_for_status()

weather_data = response.json()

print(weather_data)

The returned JSON uses the same Timeline Weather API structure as a GET request.

For example, daily weather records are available in:

weather_data["days"]

Making a POST Weather API request in JavaScript

Server-side JavaScript applications can use the Fetch API to send the same form-encoded request:

const url =
  "https://weather.visualcrossing.com/" +
  "VisualCrossingWebServices/rest/services/timeline/" +
  "London,UK/2026-08-01/2026-08-07";

const params = new URLSearchParams({
  key: "YOUR_API_KEY",
  unitGroup: "metric",
  include: "days",
  elements: "datetime,tempmax,tempmin,precip,conditions",
  contentType: "json"
});

fetch(url, {
  method: "POST",
  headers: {
    "Content-Type": "application/x-www-form-urlencoded"
  },
  body: params
})
  .then(response => {
    if (!response.ok) {
      throw new Error(
        "Weather API request failed: " + response.status
      );
    }

    return response.json();
  })
  .then(data => {
    console.log(data.days);
  })
  .catch(error => {
    console.error(error);
  });

For a public website, do not expose a private Weather API key unnecessarily in browser-side JavaScript. A server-side request or application backend is generally a better architecture for protecting credentials and controlling API usage.

Using POST with multiple locations

One of the most useful applications of HTTP POST is the Multiple Location Timeline Weather API.

The normal Timeline endpoint retrieves weather for one location per request. The multiple-location endpoint allows several locations to be submitted together:

https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timelinemulti

The locations are supplied using the locations parameter and separated with a pipe (|) character. The multiple-location API supports both GET and POST. Visual Crossing specifically recommends considering POST when the location list becomes long enough that URL length may become a problem.

For example:

curl -X POST \
  "https://weather.visualcrossing.com/VisualCrossingWebServices/rest/services/timelinemulti" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "key=YOUR_API_KEY" \
  --data-urlencode "locations=London,UK|Paris,France|Berlin,Germany|Rome,Italy" \
  --data-urlencode "datestart=next7days" \
  --data-urlencode "include=days" \
  --data-urlencode "unitGroup=metric" \
  --data-urlencode "contentType=json"

Because cURL’s --data-urlencode handles the encoding, you can supply the location list in its readable form rather than manually encoding characters such as |, commas, and spaces.

Multiple-location POST using Python

The same request can be made using Python:

import requests

url = (
    "https://weather.visualcrossing.com/"
    "VisualCrossingWebServices/rest/services/timelinemulti"
)

params = {
    "key": "YOUR_API_KEY",
    "locations": (
        "London,UK|"
        "Paris,France|"
        "Berlin,Germany|"
        "Rome,Italy"
    ),
    "datestart": "next7days",
    "include": "days",
    "unitGroup": "metric",
    "contentType": "json"
}

response = requests.post(url, data=params)
response.raise_for_status()

weather_data = response.json()

print(weather_data)

The JSON result from the multiple-location endpoint contains a locations array. Each entry contains the Timeline Weather API result for one requested location.

For example:

for location in weather_data["locations"]:
    print(location["resolvedAddress"])

    for day in location["days"]:
        print(day["datetime"], day["tempmax"], day["tempmin"])

When should I use the multiple-location endpoint?

The multiple-location endpoint is useful when an application needs a relatively small combined result and it is inconvenient to issue individual requests.

Common examples include loading weather directly into:

  • Microsoft Excel
  • Power BI
  • Google Sheets
  • Other tools where handling many separate API requests is difficult

It is not intended as a replacement for parallel single-location Timeline requests when loading large datasets. Multiple-location requests are limited to single concurrency, and the cost of each location is included in the total query cost.

For large-scale data retrieval, individual Timeline Weather API requests or other bulk-data approaches are generally more appropriate.

GET and POST return the same weather data

Changing the HTTP method does not change the basic response structure.

A Timeline request made with GET and the equivalent request made with POST return the same JSON or CSV weather data.

This means that code used to process results such as:

data.days

or:

data.currentConditions

does not need to change simply because the application moves from GET to POST.

The choice between GET and POST is primarily about how the request itself is transmitted.

Is POST more secure than GET?

POST should not be considered inherently more secure than GET.

Visual Crossing Weather API requests use HTTPS, which encrypts the HTTP request while it is being transmitted across the network.

POST can, however, reduce incidental exposure of parameters because values stored in the request body are less likely to appear in places that commonly record URLs, including:

  • Browser history
  • Web server URL logs
  • Proxy URL logs
  • Analytics systems
  • Copied or shared URLs

This can be especially useful when the request contains an API key.

However, API keys are still credentials and should be protected regardless of whether GET or POST is used.

For public websites and client-side applications, consider routing Weather API requests through your server so the API key does not need to be sent to end users.

Do I need to store POST parameters in a file?

No.

POST parameters can be constructed directly by your application, as shown in the Python, JavaScript, and cURL examples above.

In some workflows it can still be useful to store request parameters separately from the application code. For example, a batch-processing system might read different locations or query options from configuration files.

That is an application design choice rather than a requirement of HTTP POST.

Handling HTTP errors

Applications should check the HTTP status before attempting to process the Weather API response.

For example, using Python Requests:

response = requests.post(url, data=params)

try:
    response.raise_for_status()
except requests.HTTPError:
    print(response.text)
    raise

weather_data = response.json()

Similarly, JavaScript applications should check:

response.ok

before parsing the response as weather data.

This makes authentication problems, invalid parameters, usage-limit errors, and other request failures easier to diagnose.

API usage and request limits

Visual Crossing plans include usage, request, and other limits that should be followed when designing automated Weather API applications.

Using POST does not change how Weather API usage is calculated. The same request will have the same underlying query cost whether it is submitted using GET or POST.

For multiple-location requests, the cost of each location is combined into the cost of the complete request. For example, the Multiple Location Timeline documentation notes that requesting seven daily historical records for four locations results in a total query cost of 28.

Avoid using a single extremely large POST request simply because POST supports a request body. Requests should still be sized appropriately for the application and your Visual Crossing account plan.

Should I use GET or POST?

For most applications, the choice is straightforward.

Use GET when:

  • You are making a normal single-location Timeline request.
  • The request URL is reasonably short.
  • You want a request that is easy to inspect, copy, or test in a browser.

Consider POST when:

  • You have a long request.
  • You are using the Multiple Location Timeline Weather API with many locations.
  • Your HTTP client or application architecture works better with form data.
  • You want to keep additional request parameters out of the URL.

Both approaches use the same Timeline Weather API and return the same weather information.

Summary

The Visual Crossing Timeline Weather API supports both HTTP GET and POST requests.

Most applications can use GET, but POST is particularly useful when a request contains a long set of parameters or when the Multiple Location Timeline Weather API contains enough locations to make the GET URL unwieldy.

To make a POST request:

  1. Use the normal Timeline or Multiple Timeline API endpoint.
  2. Place supported additional parameters in an application/x-www-form-urlencoded POST body.
  3. Send the request using an HTTP client such as cURL, Python, JavaScript, Java, or another programming language.
  4. Process the returned JSON or CSV exactly as you would for an equivalent GET request.
  5. Keep your API key secure and design requests to remain within the limits of your Visual Crossing plan.

For the complete list of Weather API parameters, see the Timeline Weather API documentation. For requests involving more than one location, see Using the Timeline Weather API with multiple locations in the same request.