Saving base64 images to Bubble database

What I’m trying to do: I’m getting a base64 encoded image from an API, trying to save it as an image in the database.

What I’ve tried: I make the API call successfully and verify I’m getting base base64 encoded values. I’m trying to save those values to database in a workflow.

What I’m experiencing: No errors, but the image appears broken/empty in the database. I thought bubble would accept either URLs or base64 encoded strings (when creating images in the db)? This doesn’t seem to be the case… URLs work okay, base64 encoded strings don’t.

Question: despite finding a bunch of related threads on the forum, they’ve all lead to dead ends. Any chance someone knows how to do this with plain bubble (no plugins)? Seems like it should be basic.


I figured it out! Sharing for the next person, because it was totally NOT obvious and I only figured it out by trying a dozen different things.

So in my case, I receive a base64 encoded image from an API. I tried to save the image directly to the database in a dozen different ways, with no luck. Any save resulted in a broken image saved to the database.

What ended up working: Since I could get URLs to save, I wondered what would happen if I used the Data URI scheme. So used the “Arbitrary text” option to define the data scheme, and appended to it the base64 encoded string.

It worked :raised_hands:



Thank you! This worked for me as well!

1 Like

Be aware, base64 encoded data can be like 30% larger than the binary file.

If your saving to a bubble apps built in storage, itll fill up fast if you have any considerable number of users.

@mattygb85 Noted. Any suggestions on a better approach?

Would strongly recommend not saving the base64 string to your DB This will definitely bloat your DB and pages will start to load slowly. Those strings can be massive.

Did you try this plugin? EZ File Uploader / Downloader Plugin | Bubble

Seems like it should do the trick. Uploads the file to Bubble in base64 format, then you can save the returned URL to your DB as an image type.

Let me know if this helps!

The words we all hate hearing : It depends on your use case. Clearly you’re doing some sort of image processing. Why are you doing it? Is the goal to save room in your database? What sort of API are you getting the base 64 string from? Understandably most don’t want to share too many topic details, as these projects are our babies, so keep it vague and I’ll suggest what makes sense based on your use case.

@NoCodePete @mattygb85

Data Format: I’m getting the data back in that format from an API that I don’t control. I need to associate the image returned with the current user.

Data Storage: I couldn’t find any documentation on Bubble’s side describing how that data is stored. So many questions:

  • Is it deserialized and stored as binary?
  • Is it stored externally, with a URI reference stored in DB?
  • Is it stored as a string?
  • And my biggest question… what happens if I append the “Saved to S3” option (as I’m doing)? Is that now storing only the URL to the S3 asset? Or is it storing both URL and original serialized image?


I’ve looked for answers for all these questions but couldn’t find anything. So, with a lack of information, and not a tremendous amount of data at this point, I just stuffed it in the DB appending “Saved to S3” and crossed-my-fingers hoping would work as I’d expect (URL saved in DB, with image asset stored in bucket).

Any clarity and detail on how images are stored behind the scenes would be incredibly appreciated.

1 Like

@GenerativeLabs images are just stored on S3 and the links get stored in your DB. so if you have an image or file type, it is just a URL to an s3 link.

forgot about that :saved to S3 expression. that will store the image in S3 and return the URL, so yes you are saving a URL here. curious if this is actually working though - did you test it with an image element in your editor to make sure it is populating? if so, you should be good.

if not, again I would recommend the plugin above. it will essentially do the same thing, converting the base64 string into an S3 URL that you can store on your DB.

It is saved in an s3 bucket that bubble has full control of as a binary file, your database has a URL link to it. As far as “saved to s3” goes the bubble docs read as follows

When saving a file, the link that represents it on the web is saved. If it comes from an external API, it may be hosted elsewhere. To save it to Bubble’s server, to use Imgix on for instance, use this option. This occurs only in workflows that save things.
If a file is added using this operator, but the file already exists in S3, the original link will be saved. A new version will not be uploaded.

Do you have any coding experience? You have a few options here.

@NoCodePete Interesting. It seems as thought the :Save to S3 wasn’t behaving as I thought. Right clicking on image shows the path is still using the Data URI scheme :thinking: I just tried using the plugin you suggested, and I got it to work, but I don’t seem to have control over the images in the s3 storage. E.g. I couldn’t find a way to delete the image from s3 after I remove the record from the database, so I don’t think it’s going to work. Thank you for the suggestion though!

@mattygb85 Yes, a lot of experience programming. What are you thinking? Was trying to avoid writing code (hey, it’s a no-code platform :stuck_out_tongue: after all)

@GenerativeLabs deleting a record from your DB will never delete the attached files from S3. you need to use the “Delete an uploaded file” action, which you can use with the generated URL.

you have full control over the images as they are uploaded to your Bubble app’s S3.

I totally understand not wanting to write code, believe me. Sometimes its the ticket though. Bubble is built on AWS, so if I were you I would build a lambda function to solve you’re issue. Alternatively, you could also build a bubble plugin to suit your needs. As a starter, chatGPT was kind enough to help furnish some code for use as a lambda function :

const AWS = require(‘aws-sdk’);
const s3 = new AWS.S3();

exports.handler = async (event) => {
// Retrieve the base64-encoded string from the event
const base64String = event.base64_string;

// Decode the base64 string into binary data
const imageBuffer = Buffer.from(base64String, 'base64');

// Generate a random key for the S3 object
const randomKey = Math.random().toString(36).substring(2, 15) + Math.random().toString(36).substring(2, 15);

// Set up the S3 parameters
const params = {
    Body: imageBuffer,
    Bucket: 'your-bucket-name',
    Key: randomKey + '.jpg'

try {
    // Upload the image to the S3 bucket
    await s3.putObject(params).promise();

    // Return a success message
    return {
        statusCode: 200,
        body: 'Image uploaded successfully'
} catch (error) {
    // Return an error message if the upload fails
    return {
        statusCode: 500,
        body: 'Error uploading image: ' + error


That’s a good place to start, although I wouldn’t use that code completely in production. Bubble being built on AWS means that hosting the file in your own s3 bucket will mean its transfer speed when called to your app will be incredibly fast. Additionally to keep storage down you could use the node js sharp library to compress and resize the image to make it smaller, to save on s3 bucket storage. I would then use bubbles own api connector to make a call to whichever s3 service you’d like to use (I suggest a RESTAPI.)

@NoCodePete Yeah, I tried using “Delete an uploaded file” with no luck. I tried a few things: 1) I did a search for the image from my database, got its URL, passed it to the Delete an uploaded file action. No luck. 2) I did the same thing, but just tried the filename (not full url). No luck. 3) I even tried using a two different URLs-- a) one to the image on the source bucket, and b) the other that seems to be delivered through cloud front CDN. No luck. Unless the delete takes some time and ends up deleting later on, I couldn’t get it to work. I was super bummed… I really was hoping this would work.

@mattygb85 Yes,I’ll probably have to go down this path. Thank you much.

This topic was automatically closed after 70 days. New replies are no longer allowed.