VB.NET applications can retrieve historical weather, current conditions, and forecast data directly from the Visual Crossing Timeline Weather API using functionality built into modern .NET.
In this tutorial, we’ll use HttpClient to retrieve weather data and System.Text.Json to convert the returned JSON into strongly typed VB.NET classes.
The Visual Crossing Weather API provides programmatic access to historical, current, and forecast weather data. If you want to explore or download weather datasets before writing code, see Visual Crossing Weather Data.
To follow the examples, sign up for a free Visual Crossing account and obtain your Weather API key.
For the complete request and response reference, see the Timeline Weather API documentation.
What we’ll build
We’ll create a simple VB.NET console application that:
- Builds a Timeline Weather API URL.
- Retrieves weather data using
HttpClient. - Checks the HTTP response for errors.
- Parses the returned JSON using
System.Text.Json. - Displays daily weather data.
- Retrieves historical weather using the same code.
- Adds current conditions and hourly weather.
No third-party .NET packages are required.
Create a VB.NET project
You can create a new VB.NET console project using Visual Studio or the .NET command line.
For example:
dotnet new console -lang VB -n WeatherVB
cd WeatherVB
Modern .NET includes both HttpClient and System.Text.Json, so you do not need to install a separate HTTP or JSON library.
Get your Weather API key
Your Visual Crossing Weather API key authenticates each request.
Rather than placing the key directly in source code, we’ll read it from an environment variable named:
VISUAL_CROSSING_API_KEY
On Windows PowerShell:
$env:VISUAL_CROSSING_API_KEY="YOUR_API_KEY"
You can then read the key in VB.NET:
Dim apiKey As String =
Environment.GetEnvironmentVariable(
"VISUAL_CROSSING_API_KEY"
)
If String.IsNullOrWhiteSpace(apiKey) Then
Throw New InvalidOperationException(
"VISUAL_CROSSING_API_KEY is not set."
)
End If
Visual Crossing plans include usage and request limits, so applications should be designed to remain within the limits of the account plan being used.
If you’re new to the API, see Getting Started with the Weather API.
Understand the Timeline Weather API URL
The Timeline Weather API uses the following basic path structure:
/timeline/[location]/[date1]/[date2]
Only the location is required.
A forecast request for London can use:
/timeline/London%2C%20UK
A historical request for July 1, 2026 uses:
/timeline/London%2C%20UK/2026-07-01
A historical date range uses:
/timeline/London%2C%20UK/2026-07-01/2026-07-07
When dates are omitted, the Timeline Weather API returns the available forecast data.
When historical dates are included, the same endpoint returns weather for those dates.
Define the weather response classes
The Timeline Weather API returns JSON.
We can map the fields we need into VB.NET classes:
Public Class WeatherResponse
Public Property ResolvedAddress As String
Public Property Timezone As String
Public Property Days As List(Of WeatherDay)
End Class
Public Class WeatherDay
Public Property Datetime As String
Public Property Tempmax As Double?
Public Property Tempmin As Double?
Public Property Precip As Double?
Public Property Precipprob As Double?
Public Property Conditions As String
End Class
The property names correspond to fields in the Timeline Weather API response.
For example:
tempmax
tempmin
precip
conditions
are current Timeline fields. The older temp2m, datetimeStr, and precipitation names used by some legacy examples should not be used with the current Timeline response.
Build the Weather API URL
Create a function that accepts a location and optional dates:
Private Function BuildWeatherUrl(
location As String,
apiKey As String,
Optional startDate As String = Nothing,
Optional endDate As String = Nothing
) As String
Dim encodedLocation As String =
Uri.EscapeDataString(location)
Dim url As String =
"https://weather.visualcrossing.com/" &
"VisualCrossingWebServices/rest/services/timeline/" &
encodedLocation
If Not String.IsNullOrWhiteSpace(startDate) Then
url &= "/" & Uri.EscapeDataString(startDate)
End If
If Not String.IsNullOrWhiteSpace(endDate) Then
url &= "/" & Uri.EscapeDataString(endDate)
End If
Dim query As String =
"?key=" & Uri.EscapeDataString(apiKey) &
"&unitGroup=metric" &
"&include=days" &
"&elements=" &
Uri.EscapeDataString(
"datetime,tempmax,tempmin," &
"precip,precipprob,conditions"
) &
"&contentType=json"
Return url & query
End Function
Uri.EscapeDataString() ensures that locations containing spaces, commas, and other characters are correctly encoded for use in the URL.
The include parameter requests daily data, while elements restricts the response to the weather fields used by the application.
For more request options, see the Timeline Weather API documentation.
Retrieve weather data using HttpClient
Create a reusable HttpClient:
Private ReadOnly HttpClientInstance As New HttpClient()
Then create an asynchronous method that retrieves the Weather API response:
Private Async Function GetWeatherAsync(
location As String,
apiKey As String,
Optional startDate As String = Nothing,
Optional endDate As String = Nothing
) As Task(Of WeatherResponse)
Dim url As String =
BuildWeatherUrl(
location,
apiKey,
startDate,
endDate
)
Dim response As HttpResponseMessage =
Await HttpClientInstance.GetAsync(url)
Dim responseBody As String =
Await response.Content.ReadAsStringAsync()
If Not response.IsSuccessStatusCode Then
Throw New HttpRequestException(
$"Weather API request failed " &
$"({CInt(response.StatusCode)} " &
$"{response.ReasonPhrase}): " &
responseBody
)
End If
Dim options As New JsonSerializerOptions With {
.PropertyNameCaseInsensitive = True
}
Dim weather As WeatherResponse =
JsonSerializer.Deserialize(Of WeatherResponse)(
responseBody,
options
)
If weather Is Nothing Then
Throw New InvalidOperationException(
"Unable to parse Weather API response."
)
End If
Return weather
End Function
The actual API request is sent with:
Await HttpClientInstance.GetAsync(url)
The code then checks the HTTP status before attempting to parse the response.
This makes problems such as invalid API keys, invalid parameters, usage-limit errors, or invalid locations easier to diagnose.
Retrieve a weather forecast
You can now retrieve forecast weather for a location:
Dim weather As WeatherResponse =
Await GetWeatherAsync(
"London, UK",
apiKey
)
Daily weather records are available in:
weather.Days
For example:
Console.WriteLine(
$"Weather for {weather.ResolvedAddress}"
)
For Each day As WeatherDay In weather.Days
Console.WriteLine(
$"{day.Datetime}: " &
$"{day.Conditions}, " &
$"high {day.Tempmax}, " &
$"low {day.Tempmin}, " &
$"precipitation probability " &
$"{day.Precipprob}%"
)
Next
Complete VB.NET forecast example
The following example combines the main code into one console application:
Imports System.Net.Http
Imports System.Text.Json
Module Program
Private ReadOnly HttpClientInstance As New HttpClient()
Async Function Main() As Task
Dim apiKey As String =
Environment.GetEnvironmentVariable(
"VISUAL_CROSSING_API_KEY"
)
If String.IsNullOrWhiteSpace(apiKey) Then
Throw New InvalidOperationException(
"VISUAL_CROSSING_API_KEY is not set."
)
End If
Try
Dim weather As WeatherResponse =
Await GetWeatherAsync(
"London, UK",
apiKey
)
Console.WriteLine(
$"Weather for {weather.ResolvedAddress}"
)
For Each day As WeatherDay In weather.Days
Console.WriteLine(
$"{day.Datetime}: " &
$"{day.Conditions}, " &
$"high {day.Tempmax}, " &
$"low {day.Tempmin}, " &
$"precip probability " &
$"{day.Precipprob}%"
)
Next
Catch ex As Exception
Console.WriteLine(
"Unable to retrieve weather data:"
)
Console.WriteLine(
ex.Message
)
End Try
End Function
Private Function BuildWeatherUrl(
location As String,
apiKey As String,
Optional startDate As String = Nothing,
Optional endDate As String = Nothing
) As String
Dim encodedLocation As String =
Uri.EscapeDataString(location)
Dim url As String =
"https://weather.visualcrossing.com/" &
"VisualCrossingWebServices/rest/services/timeline/" &
encodedLocation
If Not String.IsNullOrWhiteSpace(startDate) Then
url &= "/" &
Uri.EscapeDataString(startDate)
End If
If Not String.IsNullOrWhiteSpace(endDate) Then
url &= "/" &
Uri.EscapeDataString(endDate)
End If
Dim query As String =
"?key=" &
Uri.EscapeDataString(apiKey) &
"&unitGroup=metric" &
"&include=days" &
"&elements=" &
Uri.EscapeDataString(
"datetime,tempmax,tempmin," &
"precip,precipprob,conditions"
) &
"&contentType=json"
Return url & query
End Function
Private Async Function GetWeatherAsync(
location As String,
apiKey As String,
Optional startDate As String = Nothing,
Optional endDate As String = Nothing
) As Task(Of WeatherResponse)
Dim url As String =
BuildWeatherUrl(
location,
apiKey,
startDate,
endDate
)
Dim response As HttpResponseMessage =
Await HttpClientInstance.GetAsync(url)
Dim responseBody As String =
Await response.Content.ReadAsStringAsync()
If Not response.IsSuccessStatusCode Then
Throw New HttpRequestException(
$"Weather API request failed " &
$"({CInt(response.StatusCode)} " &
$"{response.ReasonPhrase}): " &
responseBody
)
End If
Dim options As New JsonSerializerOptions With {
.PropertyNameCaseInsensitive = True
}
Dim weather As WeatherResponse =
JsonSerializer.Deserialize(Of WeatherResponse)(
responseBody,
options
)
If weather Is Nothing Then
Throw New InvalidOperationException(
"Unable to parse Weather API response."
)
End If
Return weather
End Function
End Module
Public Class WeatherResponse
Public Property ResolvedAddress As String
Public Property Timezone As String
Public Property Days As List(Of WeatherDay)
End Class
Public Class WeatherDay
Public Property Datetime As String
Public Property Tempmax As Double?
Public Property Tempmin As Double?
Public Property Precip As Double?
Public Property Precipprob As Double?
Public Property Conditions As String
End Class
Run the application with:
dotnet run
Retrieve historical weather
The same method can retrieve historical weather by supplying dates.
For a single date:
Dim weather As WeatherResponse =
Await GetWeatherAsync(
"London, UK",
apiKey,
"2026-07-01"
)
For a historical date range:
Dim weather As WeatherResponse =
Await GetWeatherAsync(
"London, UK",
apiKey,
"2026-07-01",
"2026-07-07"
)
The response uses the same Days collection as a forecast request, so your parsing and processing code does not need to change.
If your primary goal is to explore or download historical datasets rather than integrate them into application code, see Visual Crossing Weather Data.
Add current conditions
To retrieve current conditions as well as daily data, change:
"&include=days"
to:
"&include=current,days"
Then add:
Public Class CurrentConditions
Public Property Temp As Double?
Public Property Humidity As Double?
Public Property Conditions As String
End Class
and update WeatherResponse:
Public Class WeatherResponse
Public Property ResolvedAddress As String
Public Property Timezone As String
Public Property CurrentConditions As CurrentConditions
Public Property Days As List(Of WeatherDay)
End Class
Current conditions can then be accessed using:
weather.CurrentConditions.Temp
weather.CurrentConditions.Humidity
weather.CurrentConditions.Conditions
Retrieve hourly weather
To retrieve hourly weather, request:
include=days,hours
Define an hourly class:
Public Class WeatherHour
Public Property Datetime As String
Public Property Temp As Double?
Public Property Precipprob As Double?
Public Property Conditions As String
End Class
and add an Hours property to WeatherDay:
Public Class WeatherDay
Public Property Datetime As String
Public Property Tempmax As Double?
Public Property Tempmin As Double?
Public Property Conditions As String
Public Property Hours As List(Of WeatherHour)
End Class
You can then process hourly weather:
If weather.Days.Count > 0 Then
For Each hour As WeatherHour _
In weather.Days(0).Hours
Console.WriteLine(
$"{hour.Datetime}: " &
$"{hour.Temp}, " &
$"{hour.Conditions}"
)
Next
End If
Request only the weather elements you need
The Timeline Weather API can return many weather fields.
Use the elements parameter to request only those required by your application.
For example:
elements=datetime,tempmax,tempmin,conditions
is sufficient for a simple daily forecast.
Other available weather fields include:
temp
feelslike
humidity
dew
precip
precipprob
snow
snowdepth
windspeed
windgust
winddir
pressure
cloudcover
visibility
solarradiation
solarenergy
uvindex
conditions
icon
For the complete list, see the Timeline Weather API documentation.
Use metric or US units
The examples in this article use:
unitGroup=metric
For US units, change the request to:
unitGroup=us
The selected unit group controls units such as temperature, precipitation, wind speed, and visibility.
Handle errors in VB.NET
Weather API requests can fail for reasons such as:
- Invalid API keys
- Invalid locations
- Invalid dates
- Invalid parameters
- Account usage limits
- Network connectivity problems
The example checks:
response.IsSuccessStatusCode
before parsing the JSON response.
When the API returns an error, the code includes both the HTTP status and response body:
Throw New HttpRequestException(
$"Weather API request failed " &
$"({CInt(response.StatusCode)} " &
$"{response.ReasonPhrase}): " &
responseBody
)
The response body often contains useful information about the cause of a failed request.
System.Text.Json or Newtonsoft.Json?
Modern .NET includes System.Text.Json, which is sufficient for the Weather API examples in this tutorial and does not require an additional package.
Applications that already use Newtonsoft.Json can continue to use it with the same Timeline Weather API response.
For example, with Newtonsoft.Json:
Dim weather As WeatherResponse =
JsonConvert.DeserializeObject(
Of WeatherResponse
)(responseBody)
However, there is no need to add Newtonsoft.Json solely to process the Visual Crossing Weather API response in a modern .NET application.
Going further
Once your VB.NET application can retrieve Timeline Weather API data, the same approach can support:
- Windows desktop applications
- ASP.NET applications
- Business systems
- Background services
- Data-processing tools
- Historical weather analysis
- Current weather displays
- Hourly forecasts
- Daily forecasts
- Operational applications
The Visual Crossing Weather API provides programmatic access to historical weather, current conditions, forecasts, alerts, and additional weather information.
For interactive access to historical and forecast datasets, see Visual Crossing Weather Data.
If you haven’t created an account yet, sign up for a free Visual Crossing account.
For detailed request parameters and response fields, see the Timeline Weather API documentation.
Summary
Modern VB.NET applications can retrieve Visual Crossing Weather API data using functionality included with .NET.
The basic process is:
- Obtain a Visual Crossing Weather API key.
- Store the key outside the source code.
- Build the Timeline URL with the location and optional dates in the URL path.
- Send the request using
HttpClient. - Check the HTTP response for errors.
- Parse the JSON using
System.Text.Json. - Map the result into strongly typed VB.NET classes.
- Process daily, hourly, or current weather data in your application.
Because the Timeline Weather API provides historical, current, and forecast weather through a consistent response structure, the same VB.NET integration can support a wide range of existing and new .NET applications.

