Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Decode the Base64 payload into bytes, wrap those bytes in io.BytesIO, and open the stream with Pillow. If the input is a data URI such as data:image/png;base64,..., remove everything through the first comma before decoding. Call load() if you need Pillow to read the image pixels before the stream goes away.

Convert Base64 to a Pillow image in memory

Python’s base64.b64decode() returns bytes; it does not create an image object. Pillow’s Image.open() can read image bytes through a file-like object, and io.BytesIO provides that bridge without writing a temporary file. The function below accepts either raw Base64 or a data URI and rejects invalid Base64 rather than silently ignoring unexpected characters.

import base64
import binascii
import io
from PIL import Image


def image_from_base64(value: str) -> Image.Image:
    """Return a Pillow Image from raw Base64 or a data URI."""
    payload = value.split(",", 1)[1] if "," in value else value
    try:
        raw = base64.b64decode(payload, validate=True)
    except (binascii.Error, ValueError) as exc:
        raise ValueError("Invalid Base64 image data") from exc

    image = Image.open(io.BytesIO(raw))
    image.load()
    return image


# Examples:
image = image_from_base64(encoded_value)
print(image.format, image.size, image.mode)
image.save("output.png")

Install Pillow in the Python environment where the script runs with python -m pip install Pillow. The standard-library base64 and io modules need no separate installation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

What the function does

  1. Separate the payload. A data URI carries metadata before a comma and the Base64 payload after it. The code splits once, so additional commas in the payload are not treated as more separators. A raw Base64 string is passed through unchanged.
  2. Decode strictly. validate=True rejects characters outside the Base64 alphabet instead of discarding them. Missing or incorrect padding is still an error; the function reports it as invalid input.
  3. Make a binary stream. io.BytesIO(raw) lets Pillow read the decoded bytes using its file-like input interface.
  4. Open and load. Image.open() identifies a supported image format from the bytes. It is lazy: calling load() reads the image data before the function returns.

Handle raw Base64 and data URIs correctly

First identify which form your caller supplies. A value copied from a browser may be a complete data URI; an API field may contain only the encoded payload. Passing the entire data URI into strict Base64 decoding fails because the prefix is not Base64 image data.

#1 Best Overall
Sale
Kodak PIXPRO FZ45 Digital Camera, 16MP Point & Shoot (Black)
  • 16MP Sensor: Captures detailed photos with a CMOS sensor for everyday shooting
  • Optical Zoom: 4x optical zoom with a 27mm wide angle lens for flexible framing indoors or outdoors
  • Full HD Video: Records 1080p video for travel clips, family moments, or simple vlogging
  • Memory Support: Works with Class 10 SD, SDHC, or SDXC cards up to 512GB
  • LCD Screen and Battery: 2.7in LCD screen with 2 AA alkaline batteries for convenient on-the-go use
Input form What to decode Example
Raw Base64 The whole string iVBORw0KGgo...
Data URI Only the content after the first comma data:image/png;base64,iVBORw0KGgo...

The MIME-type label in a data URI can be useful context, but it is not a conversion instruction. Pillow identifies the image format from the decoded file bytes. If you want to accept only data URIs in a particular application, check the header before extracting the payload rather than treating any comma-containing string as a valid data URI.

Minimal code for known-clean input

If the value is already a clean raw Base64 string and you do not need explicit validation, the essential in-memory operation is:

import base64
import io
from PIL import Image

img = Image.open(io.BytesIO(base64.b64decode(encoded_image)))

For a known data URI, separate its header explicitly:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Rank #2
Sale
Kodak PIXPRO FZ55-BK 16MP CMOS Sensor Camera 5X Optical Zoom 28mm Wide
  • 16MP Sensor: Captures detailed photos with a CMOS sensor for everyday shooting
  • Optical Zoom: 5x optical zoom with a 28mm wide angle lens for flexible framing indoors or outdoors
  • Full HD Video: Records 1080p video for travel clips, family moments, or simple vlogging
  • Memory Support: Works with Class 10 SD, SDHC, or SDXC cards up to 512GB
  • LCD Screen and Battery: 2.7in LCD screen and a rechargeable lithium-ion battery for on-the-go use
header, encoded = data_uri.split(",", 1)
img = Image.open(io.BytesIO(base64.b64decode(encoded, validate=True)))

Use the complete function when inputs can be malformed or arrive in either form. The minimal versions leave input-shape and error handling to the caller.

Save, preserve, or convert the decoded image

Decoding and opening do not turn one image format into another. The opened Pillow image retains its source format and mode; the filename extension you choose is not itself a conversion. To save an image, choose a matching extension and, when needed, specify the format explicitly:

img.save("output.png")
# Or specify the format explicitly:
img.save("output.webp", format="WEBP")

If the desired output format requires a different color mode, convert the mode before saving. For example, JPEG does not support an alpha channel, so an image with transparency needs an explicit background-compositing decision before it can be saved as JPEG. Do not assume that changing .png to .jpg changes the image encoding.

Rank #3
Sale
Digital Camera, Latest FHD 1080P Digital Camera for Teens with SD Card Anti Shake Point and Shoot Cameras Portable 16X Zoom Compact Small Cameras for Kids Boys Girls Seniors with Wrist Strap
  • Latest Digital Camera Built-in Fill Light : This compact digital camera is paired with a powerful CMOS processor and image stabilization to help you take & record the most exciting moments in 44 MP quality images & FHD 1080P quality videos anywhere, anytime. Plus, there is also a built-in fill light to help you take high quality pictures even in low light&dark settings, making this the perfect camera for all indoors/outdoors situations.
  • Long-Lasting Battery Life & 16X Digital Zoom :This point and shoot camera will retain its battery charge even after long use. The controls and functions are easy to operate making this the perfect choice for children, teens and younger. This kids camera supports 16x digital zoom, you can zoom in or out the subject by pressing the W/T button for taking still photos to zoom in or out on distant objects and capture all the details you need.
  • Multifunctional & Portable Digital Camera: This cheap digital camera is slim enough to fit in your pocket. You'll easily be able to take it with you on all your indoor/outdoor activities and adventures and ideal for beginners, children and teenagers. This kids digital camera is equipped with 20 filters, anti-shaking, self-timer, continuous shooting, date stamp, time-lapse recording, smile capture, internal MIC and speaker (recording sound videos), great for your daily photography needs.
  • WEBCAM & PAUSE FUNCTION : More than just a FHD 1080p digital camera, it also works as a webcam for video calls and vlogging. Connect the camera to the computer, press shutter and power button at the same time and the camera will automatically turn on webcam mode for all your video calling and live streaming needs. The pause function allows you to pause when seeing playback videos.
  • A Must Have Photography Device : This digital camera with SD card made from high-quality materials, this retro camera is safe and durable. Perfect for all ages to develop & improve their photographic abilities and observation skills. Our dedicated and experienced 24/7 support team is available for all after purchase troubleshooting, questions and technical help.

Inspect img.format, img.mode, and img.size to see what Pillow opened. Format describes the recognized file type, mode describes the pixel representation, and size is the image dimensions. If you need a durable artifact, use save(); otherwise, the image can be used directly in memory.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Keep the stream alive when Pillow is loading lazily

Image.open() is lazy: opening identifies the image, but pixel data may be read only when needed. In the function above, image.load() runs while the BytesIO stream is still alive. This is useful when returning the image for later processing, because it avoids relying on a stream that has already been closed.

If you omit load(), keep the stream available for as long as the image may need to read from it. This matters particularly when opening an image inside a with block and then using it after that block. Animated images also need care: loading one frame does not necessarily materialize every frame. Keep the image and its backing stream available while accessing additional frames.

Rank #4
Kodak PIXPRO FZ55-RD 16MP Camera 5X Optical Zoom 28mm Wide Angle 1080p
  • 16MP Sensor: Captures detailed photos with a CMOS sensor for everyday shooting
  • Optical Zoom: 5x optical zoom with a 28mm wide angle lens for flexible framing indoors or outdoors
  • Full HD Video: Records 1080p video for travel clips, family moments, or simple vlogging
  • Memory Support: Works with Class 10 SD, SDHC, or SDXC cards up to 512GB
  • LCD Screen and Battery: 2.7in LCD screen and a rechargeable lithium-ion battery for on-the-go use
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Choose strict decoding or URL-safe Base64 deliberately

The decoder call is part of input validation. base64.b64decode(payload, validate=True) is a useful default when the sender is expected to provide standard Base64: unexpected characters are rejected, and incorrect padding raises an error. It does not repair truncated input.

Some systems explicitly use the URL-safe Base64 alphabet. If the sender confirms that encoding, use Python’s base64.urlsafe_b64decode() rather than assuming standard Base64. Follow the sender’s padding convention; do not switch decoder types just because a standard decode failed. Similarly, remove whitespace only when you know it was introduced by formatting or transport. With strict validation, whitespace is rejected rather than silently discarded.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Troubleshoot decoding and image errors

Symptom Likely cause Fix
binascii.Error: Incorrect padding The value is truncated or required = padding is missing. Obtain the complete value from its source. Do not invent padding or bytes to conceal a truncated payload.
Invalid-character error with validate=True The data URI header or whitespace was included, the value contains unrelated characters, or the sender used URL-safe Base64. Separate the data-URI payload, confirm the source encoding, and use the matching decoder. Remove whitespace only if it is known to be transport formatting.
PIL.UnidentifiedImageError The decoded bytes are not a complete supported image, the wrong part of the input was decoded, or the bytes use another encoding. Check that decoding used the payload rather than the header and that the sender supplied a complete supported image file. Base64 transports bytes; it does not make arbitrary bytes an image.
Image access fails after a with block The image was opened lazily and its underlying stream was closed before pixel data was read. Call load() before the stream closes, or keep the stream alive for later access.
Only the first animation frame is available Loading one frame does not necessarily materialize every frame. Keep the opened image and its stream available while reading further frames.
Saved image does not match its extension Changing the filename suffix does not convert the format. Save using the intended Pillow format and convert the image mode if the target format requires it.

Or skip the browser setup

If the image you need is a web page screenshot, ScreenshotNeo returns the screenshot as an image response, so you can pass the response bytes straight to Pillow instead of first converting Base64. The API accepts one GET request for a URL and can return PNG, JPEG, WebP, or PDF. See the ScreenshotNeo API documentation for its request options.

import io
import requests
from PIL import Image

r = requests.get(
    "https://api.screenshotneo.com/v1/shot",
    params={"access_key": "YOUR_API_KEY", "url": "https://stripe.com"},
    timeout=90,
)
image = Image.open(io.BytesIO(r.content))
image.load()

This is a separate path from decoding Base64: the HTTP response body contains image bytes, so there is no Base64 decoder step. ScreenshotNeo removes cookie banners, newsletter popups, and chat widgets before the shot; bot checks, blank pages, failed loads, timeouts, and cache hits are not billed. Its MCP server gives AI agents screenshot tools, and the free plan includes 1,000 screenshots per month with no card; paid plans start at $5 for 3,000. Learn about ScreenshotNeo or sign up for 1,000 free screenshots a month with no card.

FAQ

Does Base64 decoding itself verify that the bytes are an image?

No. It decodes text into bytes. Pillow’s image-opening step determines whether those bytes form a supported image.

Can I use the Pillow image without saving it to disk?

Yes. The BytesIO stream keeps the image in memory, and you can pass the loaded Pillow image to other code without creating a temporary file.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Quick Recap

SaleBestseller No. 1
Kodak PIXPRO FZ45 Digital Camera, 16MP Point & Shoot (Black)
Kodak PIXPRO FZ45 Digital Camera, 16MP Point & Shoot (Black)
16MP Sensor: Captures detailed photos with a CMOS sensor for everyday shooting; Full HD Video: Records 1080p video for travel clips, family moments, or simple vlogging
$99.99
SaleBestseller No. 2
Kodak PIXPRO FZ55-BK 16MP CMOS Sensor Camera 5X Optical Zoom 28mm Wide
Kodak PIXPRO FZ55-BK 16MP CMOS Sensor Camera 5X Optical Zoom 28mm Wide
16MP Sensor: Captures detailed photos with a CMOS sensor for everyday shooting; Full HD Video: Records 1080p video for travel clips, family moments, or simple vlogging
$139.99
Bestseller No. 4
Kodak PIXPRO FZ55-RD 16MP Camera 5X Optical Zoom 28mm Wide Angle 1080p
Kodak PIXPRO FZ55-RD 16MP Camera 5X Optical Zoom 28mm Wide Angle 1080p
16MP Sensor: Captures detailed photos with a CMOS sensor for everyday shooting; Full HD Video: Records 1080p video for travel clips, family moments, or simple vlogging
$139.99

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.