How to Load Weather Data Using VB.NET

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:

  1. Builds a Timeline Weather API URL.
  2. Retrieves weather data using HttpClient.
  3. Checks the HTTP response for errors.
  4. Parses the returned JSON using System.Text.Json.
  5. Displays daily weather data.
  6. Retrieves historical weather using the same code.
  7. 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:

  1. Obtain a Visual Crossing Weather API key.
  2. Store the key outside the source code.
  3. Build the Timeline URL with the location and optional dates in the URL path.
  4. Send the request using HttpClient.
  5. Check the HTTP response for errors.
  6. Parse the JSON using System.Text.Json.
  7. Map the result into strongly typed VB.NET classes.
  8. 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.