# Base64 Encoder & Decoder API: Text, Files, Image to Data URI (`eliai/base64-encoder-decoder`) Actor

Base64 encode and decode API: turns text, files or image URLs into Base64 and ready data: URIs, and decodes Base64 or base64url back to text or files. One JSON row per item. For developers, email builders and automation workflows. Invalid input is reported; failed items are never charged.

- **URL**: https://apify.com/eliai/base64-encoder-decoder.md
- **Developed by:** [Broke to Built](https://apify.com/eliai) (community)
- **Categories:** AI, Developer tools, Automation
- **Features:** Limited permissions
- **Stats:** 189 total users, 79 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $1.20 / 1,000 converted texts

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

### Base64 Encoder & Decoder API — Text, Files & Image to Data URI

**Encode text, or any file or image URL, to Base64 and a ready `data:` URI. Decode Base64 or base64url back to text or a downloadable file. One JSON row per item.**

| You give it | You get back | You pay (Free plan) |
|---|---|---|
| Text, a list of texts, or file URLs; `mode` = encode or decode | One JSON record per item: the Base64 (or decoded) value, alphabet, byte count | **$0.001 per text** + **$0.002 per file** (from Nov 6, 2026: $0.0015 + $0.003) |

Pay per result only: no subscription, no start fee. Failed items are recorded in the dataset and not charged. Paid Apify plans get Store discounts on the price above.

#### Try it in one click

The input form is already filled in with this example. Press **Start** and you get the output below.

```json
{}
```

Real output from that exact input (run on 2026-09-24; long arrays shortened to a few entries and long text cut for display):

```json
[
  {
    "mode": "encode",
    "input": "Hello from Apify! Base64 encoding keeps binary data safe inside JSON, URLs and email.",
    "base64": "SGVsbG8gZnJvbSBBcGlmeSEgQmFzZTY0IGVuY29kaW5nIGtlZXBzIGJpbmFyeSBkYXRhIHNhZmUgaW5zaWRlIEpTT04sIFVSTHMgYW5kIGVtYWlsLg==",
    "alphabet": "standard",
    "inputBytes": 85
  }
]
```

**Give it text or a file URL, get Base64 plus a ready-to-paste `data:` URI back — or give it Base64 and get the text or the original file back.** Batch input, strict validation, URL-safe alphabet, and per-item billing where failed items are never charged.

### Who this is for

- **Developers** who need an image, PDF, or any file as a Base64 string inside a JSON payload, an email, or a config file — without writing the fetch-and-encode glue.
- **Front-end and email builders** turning image URLs into `data:` URIs to inline into HTML, CSS `url()`, or email templates.
- **API integrators** whose upstream sends Base64 blobs (webhook payloads, attachments, JWT segments) and who need the decoded text or file back out.
- **Automation builders** (Make, Zapier, n8n) who need encode/decode as one hosted step between two other apps.
- **AI agents** that receive or must produce Base64 mid-task, via API or Apify MCP.

### What you get

One dataset row per item. Fields, exactly as the actor emits them:

| Field | When | Meaning |
|---|---|---|
| `mode` | always | `encode` or `decode` |
| `processedAt` | always | ISO timestamp for that item |
| `base64` | encode | The Base64 string (standard or `base64url` if `urlSafe`) |
| `dataUri` | encode, file | Complete `data:<mime>;base64,...` — paste straight into `<img src>` or CSS |
| `contentType` | encode, file | MIME from the server's header, or sniffed from magic bytes |
| `inputBytes` | encode | Size of the source text/file in bytes |
| `alphabet` | encode | `standard` or `base64url` |
| `url` | encode, file | The file URL you supplied |
| `base64Key` / `base64Url` | encode, huge files | Set instead of `base64` when the result exceeds ~3 MB; the payload goes to the key-value store |
| `text` | decode | Decoded content, when the bytes are valid UTF-8 |
| `textKey` / `textUrl` | decode, long text | Complete decoded text in the run key-value store, with a signed download URL |
| `textTruncatedInline` / `textCharacters` | decode, long text | `true` when `text` is a preview; length of the complete decoded text |
| `kind` | decode | `text` or `file` |
| `decodedBytes` | decode | Byte length of the decoded payload |
| `declaredMime` | decode | MIME declared inside a `data:` URI, if there was one |
| `fileKey` / `downloadUrl` | decode, binary | Key-value store key and a signed, shareable download URL |
| `error` | any failure | Plain-language reason. The row is stored; **this item is never charged** |

### Examples

All three outputs below are copied from real runs of this actor, only the long Base64 bodies are trimmed.

**1. Encode a file URL to a data URI**

Input:

```json
{ "mode": "encode", "fileUrls": ["https://apify.com/favicon.ico"] }
```

Output row:

```json
{
  "mode": "encode",
  "url": "https://apify.com/favicon.ico",
  "contentType": "image/x-icon",
  "inputBytes": 15086,
  "alphabet": "standard",
  "base64": "AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAA...",
  "dataUri": "data:image/x-icon;base64,AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAA...",
  "processedAt": "2026-08-15T16:09:30.845Z"
}
```

**2. Decode a batch, including a `data:` URI**

Input:

```json
{ "mode": "decode", "text": "", "items": ["SGVsbG8sIHdvcmxkIQ==", "data:text/plain;base64,QnJva2UgdG8gQnVpbHQ="] }
```

Output rows:

```json
[
  { "mode": "decode", "kind": "text", "text": "Hello, world!", "decodedBytes": 13, "declaredMime": null, "processedAt": "2026-08-15T16:09:12.694Z" },
  { "mode": "decode", "kind": "text", "text": "Broke to Built", "decodedBytes": 14, "declaredMime": "text/plain", "processedAt": "2026-08-15T16:09:12.746Z" }
]
```

**3. Invalid Base64 is reported, not silently mangled**

Input:

```json
{ "mode": "decode", "text": "", "items": ["not-valid-base64!!"] }
```

Output row (recorded, **not charged**):

```json
{
  "mode": "decode",
  "input": "not-valid-base64!!",
  "error": "Not valid Base64 (after accepting url-safe alphabet, whitespace and data: URIs).",
  "processedAt": "2026-08-15T16:09:12.799Z"
}
```

A plain `Buffer.from(s, 'base64')` would have returned garbage bytes here without complaining. This actor validates first.

### Input

| Field | Type | Default | Notes |
|---|---|---|---|
| `mode` | `encode` | `decode` | `encode` | |
| `text` | string | sample text | One text to encode, or a Base64 string / data URI to decode |
| `items` | string\[] | `[]` | Batch — one dataset row per item |
| `fileUrls` | string\[] | `[]` | Encode mode: public files to download & encode |
| `urlSafe` | boolean | `false` | Output base64url (`-`/`_`, no padding). Decode accepts both alphabets always |
| `decodeToFile` | boolean | `false` | Decode mode: always store the decoded bytes as a downloadable file |
| `maxFileSizeMb` | integer | `25` | Skip downloads larger than this (recorded, unbilled) |

> **One gotcha worth 10 seconds:** `text` ships with a demo string prefilled. In decode mode, clear it (or overwrite it with your own Base64) or you get one extra "not valid Base64" row from the leftover demo text. That row is free, but it is noise in your dataset.

### Call it from code

**curl** — synchronous run, results straight back:

```bash
curl -X POST "https://api.apify.com/v2/acts/eliai~base64-encoder-decoder/run-sync-get-dataset-items?token=YOUR_APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"mode":"encode","fileUrls":["https://example.com/logo.png"]}'
```

**Python** (`pip install apify-client`):

```python
from apify_client import ApifyClient
from urllib.request import urlopen

client = ApifyClient("YOUR_APIFY_TOKEN")
run = client.actor("eliai/base64-encoder-decoder").call(
    run_input={"mode": "decode", "text": "", "items": ["SGVsbG8gd29ybGQ=", "bm90IHNlY3JldA=="]}
)
for row in client.dataset(run["defaultDatasetId"]).iterate_items():
    if row.get("error"):
        print(row["error"])
    elif row.get("textTruncatedInline"):
        # The inline text is only a preview. Retrieve the complete decoded document.
        with urlopen(row["textUrl"], timeout=30) as response:
            print(response.read().decode("utf-8"))
    elif row.get("kind") == "text":
        print(row.get("text", ""))
    else:
        print(row.get("downloadUrl", ""))
```

**Node.js** (`npm install apify-client`):

```js
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: 'YOUR_APIFY_TOKEN' });
const run = await client.actor('eliai/base64-encoder-decoder').call({
    mode: 'encode',
    fileUrls: ['https://example.com/logo.png'],
});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items[0].dataUri); // ready for <img src="...">
```

### Automate it

Everything the Apify platform offers works here with zero extra code: **schedule**
recurring runs, fire a **webhook** when a run finishes, or drop it into **Make, Zapier,
or n8n** with the standard Apify app — pass the JSON input above and use the dataset
rows downstream. Agents can call it directly over **Apify MCP**.

### Pricing

One successful item produces one charge event. Rates change on November 6, 2026; both are shown below (checked October 24, 2026).

| Apify plan | Text item until Nov 6 | File item until Nov 6 | Text item from Nov 6 | File item from Nov 6 |
|---|---:|---:|---:|---:|
| Free | $0.001 | $0.002 | $0.0015 | $0.003 |
| Bronze | $0.00093 | $0.00186 | $0.0014 | $0.0028 |
| Silver | $0.00087 | $0.00174 | $0.0013 | $0.0026 |
| Gold to Diamond | $0.0008 | $0.0016 | $0.0012 | $0.0024 |

The live console tiers win if they ever differ from this table.

At Free-plan rates, 1,000 text conversions cost **$1.00** ($1.50 from Nov 6) and 1,000 file conversions cost **$2.00** ($3.00 from Nov 6). A text item is one string encoded or decoded to text. A file item is one remote file encoded or one decoded payload stored as a file. Long decoded text keeps the text event even when its full content is delivered through a download link.

Failed items return an error record and are not charged. There is no Actor subscription or start event. Check the Store Pricing tab for your account's current tier.

For code already running in Python or Node.js, the standard Base64 library may be sufficient. This Actor provides a hosted batch step, URL downloads, validation, and stored outputs for automation workflows.

### When NOT to use this

- **You are already in a script or notebook.** `base64.b64encode(open(f,'rb').read())` is free and instant. Use this when you need it as a hosted step, not as a library.
- **The file is behind a login, a paywall, or a private network.** This actor only fetches public URLs you hand it — no cookies, no auth headers, no crawling.
- **You want encryption.** Base64 is encoding, not security. Anyone can decode it. If you need secrecy, encrypt first and Base64 the ciphertext.
- **You need to encode a file you have locally but not online.** There is no file upload — the input is a URL. Host the file somewhere reachable first.
- **You need Base64 of a whole website or of a crawl.** This does not crawl; it processes the exact URLs and strings you list.

### Honest limits

- File downloads are capped at `maxFileSizeMb` (default 25 MB, hard max 100 MB) with a 60-second timeout per file.
- Content-type detection covers common formats by magic bytes (PNG, JPEG, GIF, WebP, PDF, ZIP, XML); unknown binaries are labelled `application/octet-stream` — the bytes are always exact, only the label can be generic.
- Base64 results over ~3 MB are moved to the key-value store; the dataset row then carries `base64Url` instead of `base64`.
- Decoded text over 100,000 characters has a preview in `text` and the complete original bytes at `textUrl`. It remains one text conversion, with no extra file event.
- `fileUrls` applies to encode mode only. To decode a file, pass its Base64, not its URL.

### FAQ

**How do I convert an image URL to a Base64 data URI?** Encode mode with the URL in `fileUrls`. The result row includes the raw Base64 **and** a complete `data:<mime>;base64,...` URI ready for an `<img src>`, a CSS `url()`, a JSON payload, or an email template.

**How do I decode a Base64 string back to a file?** Decode mode. Valid UTF-8 payloads come back as plain `text`; above 100,000 characters, `text` is a preview and `textUrl` downloads the complete content. Binary payloads are written to the key-value store with the content type detected from magic bytes, and the row carries a signed `downloadUrl`. Set `decodeToFile: true` to force file output even for text.

**What is URL-safe Base64 and when do I need it?** The RFC 4648 §5 alphabet: `-` and `_` instead of `+` and `/`, with padding stripped. It is required inside URLs, JWTs, and filenames. Set `urlSafe: true` when encoding; decoding accepts both alphabets automatically, so you can paste a JWT segment straight in.

**Can I decode a JWT with this?** You can decode each dot-separated segment — paste a segment into `items` and you get the header or payload JSON back as text. It does **not** verify the signature, so never trust a decoded JWT as proof of anything.

**What happens with invalid Base64 input?** It is validated before decoding and returned as an `error` row — recorded, never charged, and never the silently corrupted bytes a bare `Buffer.from(s, 'base64')` hands you.

**Is there a size limit for files?** `maxFileSizeMb` caps each download (default 25 MB, max 100 MB, 60 s each). Encoded results over ~3 MB move to the key-value store with a download URL, so dataset row limits never truncate your data.

**Can I process many items in one run?** Yes. Put texts or Base64 strings in `items` and file URLs in `fileUrls` — mix both in one encode run if you like. Each produces its own dataset row, and one bad item never stops the rest.

**Does Base64 make my data secure?** No. It is a reversible encoding designed to move binary data safely through text channels. Treat a Base64 string as plaintext.

### Changelog

- 2026-09-24: New summary at the top of this page: what you send, what you get, the price, and a real output from the prefilled example.
  **2026-09-05 (listing clarity).** Corrected the outdated price table and added current Store discount rates so you can estimate costs before running. The billing rates have not changed.

#### 2026-09-05 — Complete output for long text

Decoded text longer than 100,000 characters previously returned only a preview. The complete decoded bytes are now saved in the run's key-value store and linked through `textUrl`; `textTruncatedInline` identifies the preview. Pricing is unchanged, and this remains one text conversion.

### Who made this

Broke to Built. Questions or problems: open an issue on this Actor's Issues tab.

### For AI agents

This Actor is built to be called by software, not just by people.

- **Mount it directly as an MCP tool** — no Store search, no ranking, just this one tool:
  `https://mcp.apify.com/?actors=eliai/base64-encoder-decoder`
- **Or call it over HTTP** and get the results in the same request:
  `POST https://api.apify.com/v2/acts/eliai~base64-encoder-decoder/run-sync-get-dataset-items`
- **Costs are predictable before you call.** Pricing is pay-per-event (see Pricing above), so an agent can budget a run in advance instead of discovering the bill afterwards.
- **Send only the field you mean.** If you pass the bulk field, it is used on its own; the single-value field is a fallback, never merged into your request. You are charged for the items you sent and nothing else.

# Actor input Schema

## `mode` (type: `string`):

`encode` turns text or files into Base64. `decode` turns Base64 back into text (or a downloadable file — see Store decoded file).

## `text` (type: `string`):

A single text to encode — or a Base64 string to decode. Data URIs (`data:...;base64,xxxx`) are accepted in decode mode. Leave empty if you only use Batch items or File URLs.

## `items` (type: `array`):

Process many texts (or Base64 strings) in one run — one dataset row each.

## `fileUrls` (type: `array`):

Public file URLs to download and encode to Base64. Each result includes the raw Base64, a ready-to-paste `data:` URI, the content type and the byte size. Encode mode only.

## `urlSafe` (type: `boolean`):

Use `-` and `_` instead of `+` and `/` and drop `=` padding (RFC 4648 §5). Decode mode accepts both alphabets automatically regardless of this setting.

## `decodeToFile` (type: `boolean`):

In decode mode, store the decoded bytes in the run's key-value store and return a direct download URL. The file type is detected from magic bytes (PNG, JPEG, GIF, WebP, PDF, ZIP, …).

## `maxFileSizeMb` (type: `integer`):

Downloads larger than this are skipped (recorded, never charged).

## Actor input object example

```json
{
  "mode": "encode",
  "text": "Hello from Apify! Base64 encoding keeps binary data safe inside JSON, URLs and email.",
  "items": [],
  "fileUrls": [],
  "urlSafe": false,
  "decodeToFile": false,
  "maxFileSizeMb": 25
}
```

# Actor output Schema

## `results` (type: `string`):

Every item this run produced. Export as JSON, CSV or Excel from the dataset view.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {};

// Run the Actor and wait for it to finish
const run = await client.actor("eliai/base64-encoder-decoder").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {}

# Run the Actor and wait for it to finish
run = client.actor("eliai/base64-encoder-decoder").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{}' |
apify call eliai/base64-encoder-decoder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,eliai/base64-encoder-decoder"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/3UhrH3ItLIhaCV4tM/builds/u4AwYU4essauCO2Sj/openapi.json
