Do you have to deal with Base64 format? Then this site is perfect for you! Use our super handy online tool to encode or decode your data.

Base64 Decoding in Visual Basic: A Complete Guide

Picture the scene: a string lands in your Visual Basic project. It looks like a shuffled deck of letters and digits, with the occasional plus sign, slash, or equals sign mixed in, and the person who sent it swears it was once a perfectly ordinary sentence, a JPEG, or a configuration blob. That string is Base64, and this page is your field guide to turning it back into what it was. The good news up front: Visual Basic has had a first-class Base64 decoder since the very early .NET Framework days, it ships inside the runtime, and you do not need to install a single package to use it.

A quick refresher, because the home page of this site explains the format in full depth: Base64 writes three bytes as four characters drawn from a 64-symbol alphabet, and one or two trailing = characters mark where the real data ended. So encoded text is a little puffy compared to the original: four characters for every three input bytes, roughly a third more. Decoding simply runs that trade in reverse. With the shape of the problem in mind, let us open some envelopes.

The Decoder Family: One Class, Four Eras

Everything you need for decoding lives in the .NET runtime. Over the last two decades it has grown in four waves, and the older waves still work exactly as they always did, so you will see all of them in the wild:

API Available since What it is for
System.Convert.FromBase64String .NET Framework 1.1 (2003) The classic. One string in, a fresh Byte() array out. Throws on bad input.
System.Convert.FromBase64CharArray .NET Framework 1.1 (2003) The same decode, reading from a slice of a character array you already own.
System.Convert.TryFromBase64String, TryFromBase64Chars .NET Core 2.1 (2018) Boolean instead of exceptions, writing into a buffer you provide. The friendly guard for untrusted input.
System.Buffers.Text.Base64 .NET Core 2.1 (2018) Low-level, span-based decoding: status codes instead of exceptions, in-place deflation, and IsValid pre-checks.
System.Buffers.Text.Base64Url .NET 9 (2024) The URL-safe alphabet (- and _ instead of + and /), with optional padding. On older runtimes it rides in the Microsoft.Bcl.Memory NuGet package.
FromBase64Transform + CryptoStream .NET Framework 1.1 (2003) Streaming decoding: file to file, network to disk, chunk by chunk, without holding the whole payload in memory.

One Visual Basic clarification before we go further. In a VB project the bare name Convert resolves to System.Convert, because the standard project templates import the System namespace for you, and nothing in the Visual Basic runtime shadows that name. Still, this article mostly writes the full System.Convert form: it costs nothing, and it makes the intent unmistakable to anyone reading the code.

On versions: .NET 10 is the current long-term-support release (November 2025, supported until November 2028), and .NET 8 and .NET 9 both remain supported until November 2026, while .NET 11 is in preview and adds a batch of new Base64 convenience methods. The decoding APIs are stable across all of them. The only version gate is Base64Url: it is built in from .NET 9 onward, and on .NET Framework 4.6.2 or newer you can pull it in with the Microsoft.Bcl.Memory package. Nothing else in this article needs a package.

If you are setting up from scratch, the .NET SDK includes Visual Basic out of the box, so this is the whole ceremony:

dotnet new console -lang VB -o EnvelopeOpener
cd EnvelopeOpener
dotnet run

That gives you a small Program.vb with Imports System at the top, and you are ready to decode.

The One-Liner: FromBase64String

Ninety percent of decoding life in Visual Basic is a single call. Hand it a string, and it hands back the exact bytes that were packed inside:

Imports System
Imports System.Text
Module EnvelopeOpener
    Sub Main()
        Dim packed As String = "TWFu"
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        Dim text As String = Encoding.UTF8.GetString(bytes)
        Console.WriteLine(text)
        ' Man
    End Sub
End Module

Three things are worth fixing in your mind. First, the result is bytes, not text: the decoder is byte-oriented end to end, which is exactly what you want, because the payload might be a sentence, a JPEG, a certificate, or a hash, and none of them should be treated specially. Turning those bytes into a readable string is a separate, deliberate step through an Encoding object, and that step is where your character set decision lives (more on that below). Second, FromBase64String allocates a fresh array sized to exactly the decoded length, so you never carry spare capacity around. Third, "TWFu" decodes to the word "Man", three bytes, zero surprises, which makes it the perfect smoke test for any decode code you write.

What the Decoder Forgives, What It Refuses

Here is where the .NET decoder has a personality, and a characterful one: it is generous about one thing and merciless about everything else. The generous thing is whitespace. The decoder skips exactly four characters, no matter where they appear: the space (U+0020), the tab (U+0009), the line feed (U+000A), and the carriage return (U+000D). That policy is a deliberate nod to email, where Base64 payloads arrive wrapped in short lines, and it means a MIME-wrapped attachment decodes with zero preprocessing. A fun fact: this leniency is shared by the whole built-in family, including the span-based System.Buffers.Text.Base64 and the URL-safe Base64Url classes, so you get the same forgiving behavior no matter which API you reach for. Anything outside the 64-symbol alphabet, any broken length rule, or any misplaced padding earns an exception. Here is the same decoder meeting a few different inputs:

Input Result
"TWFu" Decodes to Man (3 bytes).
"TWF" + CRLF + "u" Decodes to Man. Line breaks in the middle are invisible to the decoder.
"TWFu" + non-breaking space FormatException. Only the four whitespace characters above are skipped; a non-breaking space is not one of them.
"TWE" FormatException. Ignoring whitespace, the length must be a multiple of 4.
"TWFu=" FormatException. Padding after the data is over is not allowed.
"====" FormatException. More than two padding characters is invalid.
"" or whitespace only An empty byte array. A quiet, valid success.
"TW=u" FormatException. Padding in the middle is invalid.

So the honest contract is small and memorable: a Nothing reference throws ArgumentNullException, an empty or whitespace-only input decodes to an empty array, valid input decodes to bytes, and everything else invalid throws one very specific exception, FormatException.

From Bytes to Text: Choosing the Character Set

The moment you decide the decoded bytes are actually text, you have to name a character set, because bytes are not text until you say how to read them. Visual Basic strings are internally UTF-16, but the bytes coming out of the decoder were made by someone else, probably under a different scheme, so you have to match their choice. The practical menu:

  • Encoding.UTF8: the safe default for anything that traveled over the web or through an API. If in doubt, start here.
  • Encoding.Unicode: UTF-16 little-endian, the native flavor of .NET. Reasonable when both sides of the exchange are .NET programs that explicitly chose UTF-16.
  • Encoding.ASCII: 7-bit only. Non-ASCII bytes are replaced with a question mark, so this is a lossy choice that quietly destroys accents.
  • Encoding.Default: the ANSI code page of the machine your code runs on. It is locale-dependent, so the same bytes decode differently on different computers. Avoid it for data you exchange with other systems.
Imports System
Imports System.Text
Module CharsetDemo
    Sub Main()
        ' The word "Café" stored as UTF-8 bytes
        Dim bytes() As Byte = System.Convert.FromBase64String("Q2Fmw6k=")
        Dim correct As String = Encoding.UTF8.GetString(bytes)
        Console.WriteLine(correct)
        ' Café
    End Sub
End Module

Read those same four bytes with Encoding.Unicode instead and you get a single bizarre character, because the decoder pairs the bytes up differently. Read the UTF-8 bytes of "Café" with Encoding.ASCII and the accent becomes ?. None of these choices throw an exception; they just quietly produce the wrong text, which is why the character set is a decision you make on purpose, not a default you inherit.

The URL-Safe Alphabet: Base64Url

Standard Base64 uses + and /, and both of those characters carry their own meanings inside URLs, so a standard alphabet can break a link the moment it lands in a query string. The fix, standardized in RFC 4648 section 5, is the URL- and filename-safe variant: the same 64-character scheme with - taking the place of + and _ taking the place of /, and with the trailing padding typically dropped because it is implied by the length. You will meet this alphabet in JWTs, API tokens, and anywhere Base64 rides inside a URL. .NET 9 added a dedicated class for it, System.Buffers.Text.Base64Url, and it is a joy to use:

Imports System.Buffers.Text
Imports System.Text
Module UrlSafeOpener
    Sub Main()
        ' URL-safe input, no padding at the end
        Dim packed As String = "SGVsbG8gd29ybGQ"
        Dim bytes() As Byte = Base64Url.DecodeFromChars(packed)
        Dim text As String = Encoding.UTF8.GetString(bytes)
        Console.WriteLine(text)
        ' Hello world
    End Sub
End Module

Two behaviors are worth knowing. The Base64Url encoder produces output without padding by design, but its decoder accepts both padded and unpadded input, so it is friendly to data from other ecosystems. And Base64Url.IsValid lets you pre-check a candidate string before you decode, which is handy when the data comes from the outside world. If you are stuck on an older runtime without the class, the conversion is two character swaps and a padding top-up, exactly the reverse of what the encoder did:

Imports System
Module CompatOpener
    Function FromUrlSafe(ByVal packed As String) As Byte()
        Dim standard As String = packed.Replace("-"c, "+"c).Replace("_"c, "/"c)
        Select Case standard.Length Mod 4
            Case 2
                standard &= "=="
            Case 3
                standard &= "="
        End Select
        Return System.Convert.FromBase64String(standard)
    End Function
End Module

On .NET Framework 4.6.2 or newer you can instead install the Microsoft.Bcl.Memory NuGet package and use the real Base64Url class. Either way, the rule is simple: recognize the alphabet from the context (URL, JWT, API token), then pick the matching decoder.

Opening Files

One of the oldest uses of Base64 is smuggling binary through text files: a .b64 or .txt file that contains encoded bytes. In Visual Basic the round trip is two file calls and one decode. Read the text, decode it, write the bytes:

Imports System.IO
Module FileOpener
    Sub Main()
        Dim packed As String = File.ReadAllText("payload.b64")
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        File.WriteAllBytes("payload.bin", bytes)
    End Sub
End Module

The whitespace forgiveness makes this robust in a satisfying way: the file does not care if the payload was written as one long line, wrapped at 76 characters, or wrapped at 64, because the decoder skips the line breaks either way. Keep one sizing fact in your back pocket: the text file is about a third larger than the binary it hides, so a 10 megabyte file arrives as roughly 13.4 megabytes of characters. Nothing dramatic, but it is the number to remember when a "small" text file feels large.

Images and Data URIs

The data URI scheme (RFC 2397) lets a URL carry its own content: data: followed by the media type, the literal marker ;base64, a comma, and then the encoded bytes. You have seen it all over the web, in HTML and CSS, where it embeds small images and fonts directly in the markup instead of pointing at a separate file. In Visual Basic, unpacking one is just a string split and a decode. The example below pulls a PNG out of a data URI and builds a WPF image from it:

Imports System.IO
Imports System.Windows.Media.Imaging
Module DataUriOpener
    Function ImageFromDataUri(ByVal dataUri As String) As BitmapImage
        Dim comma As Integer = dataUri.IndexOf(","c)
        Dim header As String = dataUri.Substring(0, comma)
        If Not header.EndsWith(";base64") Then
            Throw New FormatException("Not a base64 data URI")
        End If
        Dim packed As String = dataUri.Substring(comma + 1)
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        Dim image As New BitmapImage()
        image.BeginInit()
        image.CacheOption = BitmapCacheOption.OnLoad
        image.StreamSource = New MemoryStream(bytes)
        image.EndInit()
        Return image
    End Function
End Module

Notice the defensive check on the header: a data URI without the ;base64 marker contains URL-escaped data instead, and decoding that as Base64 would either fail or produce garbage. The RFC itself warns that data URIs are only useful for short values, and HTML has its own attribute length limits, so treat this as the right tool for icons, avatars, and thumbnails rather than for shipping your whole photo library in one attribute.

HTTP, APIs, and Basic Auth

Base64 is everywhere in web APIs, and the two most common appearances are the HTTP Basic auth header and JSON fields that carry binary or pre-encoded data. Basic auth is the simplest case: the server sends Authorization: Basic followed by the Base64 of username:password. Decoding it in Visual Basic is a prefix check and one call:

Imports System
Imports System.Text
Module BasicAuthOpener
    Function ReadCredentials(ByVal header As String) As String
        If Not header.StartsWith("Basic ", StringComparison.OrdinalIgnoreCase) Then
            Throw New FormatException("Not a Basic auth header")
        End If
        Dim packed As String = header.Substring(6)
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        Return Encoding.UTF8.GetString(bytes)
    End Function
End Module

The function hands back username:password as a single string, which you then split on the colon. The other everyday case is a JSON response where some field is a pre-encoded blob, like an image or a certificate. With HttpClient and System.Text.Json (both in the box since .NET Core 3.0) the pattern is straightforward:

Imports System.Net.Http
Imports System.Text.Json
Module ApiOpener
    Async Function ReadImageAsync() As Byte()
        Using client As New HttpClient()
            Dim json As String = Await client.GetStringAsync("https://api.example.com/widget/42")
            Dim doc As JsonDocument = JsonDocument.Parse(json)
            Dim packed As String = doc.RootElement.GetProperty("image").GetString()
            Return System.Convert.FromBase64String(packed)
        End Using
    End Function
End Module

Two housekeeping notes. Never print a decoded credential to a log or a UI just because you can, and never rely on Basic auth over plain HTTP, because then you have simply spelled out the password in a more interesting alphabet.

JWTs: Reading the Three Pieces

A JSON Web Token in its compact form is three dot-separated pieces of Base64Url: the header, the payload, and the signature. The first two are plain JSON that you can read with your eyes (or with one decode call), while the third is a cryptographic signature that must be checked with the right key, not decoded. A sample token from a common demo looks like this: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIn0.W-5gI_FdnMBdpgG4twX96rptvh13gmXQ75kKLRXVaGs. Reading its payload in Visual Basic means splitting on the dots, converting the URL-safe alphabet back to the standard one, and decoding:

Imports System
Imports System.Text
Module JwtOpener
    Function ReadPayload(ByVal token As String) As String
        Dim parts() As String = token.Split("."c)
        If parts.Length <> 3 Then
            Throw New FormatException("Not a compact JWT")
        End If
        ' Convert the URL-safe alphabet back to the standard one
        Dim packed As String = parts(1).Replace("-"c, "+"c).Replace("_"c, "/"c)
        Select Case packed.Length Mod 4
            Case 2
                packed &= "=="
            Case 3
                packed &= "="
        End Select
        Dim bytes() As Byte = System.Convert.FromBase64String(packed)
        Return Encoding.UTF8.GetString(bytes)
    End Function
End Module

Run that against the sample token and you get the JSON {"sub":"1234567890","name":"John Doe"}. Read the header the same way and you get {"alg":"HS256","typ":"JWT"}. The warning that matters here: reading a JWT is not verifying it. Anyone can craft a token, so before you trust any claim inside one, validate the signature with the issuer's key. For that job, the System.IdentityModel.Tokens.Jwt NuGet package (the IdentityModel suite from the Microsoft Entra team) handles the Base64Url details, the signature check, and the claim parsing for you, which is exactly the layer where you do not want to be rolling your own.

Email Attachments, Wrapped at 76 Characters

Email is where Base64 earned its reputation. SMTP was designed for 7-bit ASCII, so a binary attachment has to become text before it can fly, and the MIME standard (RFC 2045) chose Base64 with a 76-character line limit, a rule inherited from the even older 64-character lines of PEM. If you have ever received a raw email, you have seen the result: a block of dense Base64, broken into neat short lines, under a Content-Transfer-Encoding: base64 header. The beautiful part for a decoder is that you do not have to unwrap anything. The .NET decoder skips line breaks and spaces wherever they appear, so the wrapped block decodes as-is:

Imports System
Imports System.Text
Module MimeOpener
    Sub Main()
        ' A 59-byte sentence, MIME-wrapped at 76 characters with CRLF
        Dim wrapped As String = "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZywgYW5kIHRoZW4gc29t" & vbCr & vbLf & "ZS4="
        Dim bytes() As Byte = System.Convert.FromBase64String(wrapped)
        Console.WriteLine(Encoding.UTF8.GetString(bytes))
        ' The quick brown fox jumps over the lazy dog, and then some.
    End Sub
End Module

If you are working with the System.Net.Mail classes, the decoding is even more invisible: an Attachment you add to a MailMessage carries a ContentEncoding of TransferEncoding.Base64, and the mail library wraps, sends, and unwraps the whole ritual for you. You only need the manual decode when you are reading raw MIME from a stream, a test fixture, or a legacy mailbox file.

Databases, Configuration, and Environment Variables

Text-only storage keeps asking for Base64: a database column typed as text, an XML configuration value, an environment variable. All of them want plain characters, so binary gets encoded before it is stored and decoded when it comes back. The decode side is always the same one-liner, and the interesting part is the size math. A regular NVARCHAR column in SQL Server tops out at 8,000 characters, which means about 6,000 bytes of binary before the 33 percent tax pushes you over; past that you reach for the MAX variants or, more honestly, for a real binary column. On Windows, the entire environment block for a process is capped around 32 kilobytes, so "store the whole license blob in an env var" has a hard ceiling too. Here is a decode side that is worth keeping in a corner of your head: checking a stored fingerprint against a file, with a constant-time comparison so a mismatch does not leak timing information:

Imports System.Security.Cryptography
Module FingerprintCheck
    Function FingerprintsMatch(ByVal expectedPacked As String, ByVal fileBytes() As Byte) As Boolean
        Dim expected() As Byte = System.Convert.FromBase64String(expectedPacked)
        Dim actual() As Byte = SHA256.HashData(fileBytes)
        Return CryptographicOperations.FixedTimeEquals(expected, actual)
    End Function
End Module

The same shape works for any stored hash: decode the stored value, compute the fresh hash, and compare in fixed time. Configuration files follow the identical pattern, whether the value came from an XML app.config entry, a JSON settings file, or a registry string.

Big Data: Decode a Stream Without Loading It

Every example so far has read the whole payload into memory, which is fine for attachments and config values but wrong for a two gigabyte file that someone encoded into a text file. For that scale, .NET has a streaming pair that has existed since the first .NET Framework: the FromBase64Transform crypto transform wrapped in a CryptoStream. You read chunks of encoded text, the transform decodes them on the fly, and you write the bytes out, so memory stays flat no matter how large the file is:

Imports System.IO
Imports System.Security.Cryptography
Module StreamOpener
    Sub DecodeFile(ByVal packedPath As String, ByVal outputPath As String)
        Using packedStream As New FileStream(packedPath, FileMode.Open, FileAccess.Read)
            Using decodedStream As New CryptoStream(packedStream, New FromBase64Transform(), CryptoStreamMode.Read)
                Using outputStream As New FileStream(outputPath, FileMode.Create)
                    Dim buffer(65535) As Byte
                    While True
                        Dim read As Integer = decodedStream.Read(buffer, 0, buffer.Length)
                        If read = 0 Then Exit While
                        outputStream.Write(buffer, 0, read)
                    End While
                End Using
            End Using
        End Using
    End Sub
End Module

Because the encoded file is plain ASCII text, reading it as a byte stream is perfectly safe, and the transform copes with the line wrapping without you doing anything. The output file comes out roughly three quarters the size of the input, which is the same 33 percent tax paid on the way in, collected on the way out.

Pitfalls That Bite Visual Basic Specifically

Most of the traps in this section are shared with other .NET languages, but a few wear a distinctly VB hat, so here they are together:

  • Byte versus Byte(). In Visual Basic a single byte is Byte and an array of bytes is Byte(), with the empty parentheses doing all the work. Writing Dim b As Byte when you meant Byte() is the classic first-day mistake, and it is exactly the sort of thing Option Strict On catches at compile time. If your project does not have it on already, turn it on: the dotnet new console -lang VB template leaves the decision to you, while the Visual Studio project templates set it.
  • The span wall. The modern span-based APIs are callable from VB, but only at the call site: you can hand a Byte() or Char() array straight into a method that takes a span, and the compiler converts it for you. What you cannot do is name a span in your own code. Declare a variable, a field, or a parameter of type Span or ReadOnlySpan and the compiler answers with "Types with embedded references are not supported in this version of your compiler". So the VB idiom is: call the span APIs with plain arrays, and never try to store a span in a variable.
  • BitConverter is not Base64. BitConverter.ToString(bytes) renders bytes as hex, separated by dashes, which makes it a tempting wrong answer for anyone who has heard "convert bytes to string". It will happily hand you 4D-61-6E when the API expects TWFu. When in doubt, reach for System.Convert.
  • MidB is a ghost. Classic Visual Basic had byte-level string functions, MidB, LeftB, and RightB, aimed at double-byte character sets. Every .NET string is Unicode now, and the runtime documentation is blunt: they are no longer supported. If a legacy snippet uses them, rewrite it with byte arrays and the APIs in this article.
  • Encoding.Default follows the machine. The Default encoding is whatever ANSI code page the operating system happens to use, so code that decodes with it on a Western-locale machine produces different text on a Japanese-locale one. For data you share, name the encoding explicitly, usually Encoding.UTF8.
  • Round trips are not identity. If you decode a string and then encode the result, the new string is not guaranteed to match the original one: whitespace disappears, and padding is normalized. A payload with line breaks comes back as one clean line. Fine for data, dangerous if your logic compares the encoded text instead of the decoded bytes.
  • Whitespace-only input is a quiet success. A string of just spaces and line breaks decodes to an empty byte array without any error, which means "the user pasted nothing but newlines" looks exactly like "the user pasted an empty payload". If the distinction matters, check the input length before you decode.

Best Practices for Decoding

Distilled from everything above, the habits that keep decode code boring (in the best sense):

  • Treat Base64 as transport, not protection. It is an encoding, not encryption: anyone can read the original with one function call, and RFC 4648 even notes that sloppy alphabet handling can open covert channels. Encrypt first, then encode if you need to hide content.
  • For untrusted input, prefer the Try methods or an IsValid pre-check over letting FormatException fly. A boolean is easier to turn into a friendly error message than an exception is to swallow.
  • Choose the character set deliberately, and default to UTF-8 unless you have a documented reason for another scheme.
  • Match the alphabet to the source: standard Base64 for MIME, email, and config; Base64Url for JWTs and anything inside a URL.
  • Stream anything large through FromBase64Transform and CryptoStream instead of loading it into a string.
  • Compare fingerprints and hashes with CryptographicOperations.FixedTimeEquals, not =, so timing does not leak how much of the value matched.
  • Keep Option Strict On so the Byte/Byte() family of slips is a compile error instead of a production mystery.

How Visual Basic Got Its Decoder

The story starts in an era when Visual Basic had no Base64 at all. In the Visual Basic 6 and VBA world (the macro language still running inside Excel and Office today), developers who needed Base64 borrowed it from the COM components already on the machine. The famous trick used the ADO Stream object: open it as a binary stream, write your bytes, then flip it to a text stream with the special base64 charset and read the text back. Decoding ran the trick in reverse, writing the encoded text into a text stream and reading the bytes out of the binary one:

' The classic VB6 / VBA decode trick, for context
Dim stream As New ADODB.Stream
stream.Type = 2              ' adTypeText
stream.Charset = "base64"
stream.Open
stream.WriteText packed      ' the Base64 string
stream.Position = 0
stream.Type = 1              ' adTypeBinary
Dim bytes() As Byte = stream.Read

It worked, it was clever, and it is the reason "base64 VBA" still lights up search engines three decades on. Then 2002 changed everything: Visual Basic 7.0 (the first .NET version of the language, with Visual Basic .NET) joined the new Common Language Runtime, and the .NET Framework brought System.Convert with FromBase64String and its friends out of the box. From .NET Framework 1.1 in 2003, every VB program had a first-class decoder with no components to register. The modern wave arrived in 2018 with .NET Core 2.1, which added the exception-free Try methods and the fast span-based System.Buffers.Text.Base64 class, and in 2024 with .NET 9, which finally standardized the URL-safe alphabet as Base64Url. As of 2025, .NET 10 is the long-term-support release, and the preview .NET 11 libraries are adding a new generation of Base64 convenience methods, so the decoder keeps getting better even as the original one-liner from 2003 carries on unchanged.

Fun Facts From the VB World

  • The official Visual Basic compiler is itself written in Visual Basic. As part of the open-source Roslyn project, the language compiles itself.
  • The very first Visual Basic shipped in 1991, five years before the World Wide Web existed. Base64's big moment arrived with MIME in 1993, a few years before VB itself turned 32-bit with Visual Basic 5 and 6.
  • The byte-level functions MidB, LeftB, and RightB from classic VB are officially "no longer supported" in .NET, because every VB string has been Unicode since day one of the framework. A whole family of APIs, retired by an encoding choice.
  • The runtime's Base64 machinery is not a quaint table lookup: the modern implementation runs hardware-vectorized code paths (AVX-512, AVX2, and SSE variants) when the machine supports them, so "slow text codec" is not what is happening under the hood.
  • The ADO Stream trick from the VB6 era still runs in production Excel macros today, which means a workaround from the late 1990s and a Convert call from 2003 are happily coexisting in the same organization's codebase.

Before You Go

This article has covered the decoding side of Base64 in Visual Basic, from the one-liner to streaming, from JWTs to the pitfalls that wear a VB hat. The other half of the coin, turning your bytes and text into Base64 in the first place, has its own set of decisions about padding, line breaks, and the size tax, and it is covered in full detail in the companion encoding article on the sister site. The link to it sits just below this line, and the tool on the home page remains the fastest way to check a small payload by hand.

Last updated: 2026-08-30

Related article: Base64 Encoding in Visual Basic: A Complete Guide