# MOBI to EPUB Converter - AZW3, AZW and PRC (`marcel-rbro/mobi-to-epub`) Actor

Convert MOBI to EPUB in seconds, along with AZW, AZW3 and PRC. Drop in one ebook or a whole shelf - up to 100 files a run, returned as a single ZIP. Amazon stopped delivering MOBI in 2022, so this puts old Kindle files back on Kobo, Apple Books, Nook or Send to Kindle. DRM-free only.

- **URL**: https://apify.com/marcel-rbro/mobi-to-epub.md
- **Developed by:** [Marcel Rebro](https://apify.com/marcel-rbro) (community)
- **Categories:** Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

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

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

Convert **MOBI to EPUB** online, along with DRM-free PRC, AZW and AZW3 files. Upload one ebook or a whole folder of them, or paste direct URLs, and get the EPUBs back. No calibre install, no account on some ebook forum, no desktop software.

Amazon retired MOBI: the Kindle Store stopped accepting it in 2021 and Send to Kindle stopped delivering it in August 2022. EPUB is what Amazon, Kobo and Apple Books all take now - Amazon converts it to its internal KFX format on delivery. So a `.mobi` file in your library is a book you can no longer send to your own Kindle until you convert it.

- 📚 **Converts the whole Kindle family** - `.mobi`, `.prc`, `.azw` and `.azw3`, as long as they are DRM-free
- 📦 **Converts a whole library in one run** - up to 100 books at a time, returned as a single ZIP
- ⏭️ **A DRM-protected book does not stop the batch** - it is skipped with a reason and the rest of the library still converts
- 📖 **EPUB 3 by default, EPUB 2 on request** - EPUB 3 is what Send to Kindle, Kobo and Apple Books expect
- ✍️ **Fixes the metadata on the way through** - override a wrong title or author before the book reaches your library
- ❞ **Smartens punctuation** - straight quotes, hyphens and `...` become typographic quotes, dashes and ellipses
- 💸 **An ordinary novel costs a fraction of a cent**
- 🔌 **Runs from the API, a schedule or an integration** - it is an Apify Actor, so Zapier, Make, n8n and MCP clients can call it

### How to convert MOBI to EPUB

1. Click **Try for free** and sign in to Apify.
2. Upload your `.mobi` file in the **Ebooks** field, or paste a direct URL to it.
3. Leave **EPUB version** on `3` unless you are targeting an old reader.
4. Click **Start**.
5. Download the EPUB from the **Storage** tab, or from the download URL in the run's dataset record.

#### How to convert AZW3 to EPUB

Identical steps with an `.azw3` file. AZW3 (also called KF8) is the newer Kindle format and generally converts with better formatting than old MOBI does, because it carries real CSS rather than the HTML 3.2 subset MOBI was built on. `.azw` and `.prc` go through the same path.

#### How to convert a whole ebook library to EPUB

Upload the folder into the **Ebooks** field - up to 100 books, 200 MB of source files in one run - or pass an array of direct URLs in `files`. Every book is converted separately with the same settings, each EPUB is stored under its own filename, and the run's `OUTPUT` is a single `epubs.zip` holding all of them.

A mixed library is the normal case, so nothing in it is fatal on its own. A DRM-protected book, a `.mov` that ended up in the folder, a URL that returns an error page - each fails only itself, gets a dataset record saying why, and the run carries on. The log ends with how many books converted, how many failed and how many of those failures were DRM.

Two things worth knowing before starting a batch. A batch takes longer than the 300 second `run-sync` window, so call the asynchronous endpoint rather than waiting on the response. And a batch gives each book five minutes of conversion time out of 30 for the run, where a book converted on its own gets the full 15 minutes - so convert an omnibus of the Shakespeare kind on its own.

#### How to send a converted book to a Kindle

Convert to EPUB 3, then email the file to your Send to Kindle address or drop it into the Send to Kindle web page. Amazon converts EPUB to its own KFX format on delivery, which is why producing KFX here would be pointless.

### Input

Upload the ebooks in the **Ebooks** field, or pass direct URLs to them.

| Field | Description |
|---|---|
| `files` | The ebooks to convert. Uploads or URLs, up to 100 per run. |
| `epubVersion` | `3` (default) or `2`. Applies to every book in the run. |
| `outputFilename` | Names a single converted book. Ignored in a batch, where each EPUB keeps its own filename. |
| `bookTitle`, `bookAuthors` | Override the EPUB metadata. Separate authors with `&`. Single book only. |
| `smartenPunctuation` | Convert quotes, dashes and ellipses to typographic equivalents. |
| `file` | One ebook as a URL. An alias kept so callers written against the single-file input keep working. |
| `fileBase64`, `filesBase64`, `filename` | The bytes as base64, for API callers who prefer JSON to a URL. |
| `verboseLog` | Include the full calibre log in the Actor log. |

### Output

One book: the EPUB is written to the run's key-value store under `OUTPUT` and under its own filename, so `run-sync` returns it in the response body and it is downloadable from the **Storage** tab.

Several books: each EPUB is stored under its own filename, and `OUTPUT` is `epubs.zip` holding all of them. Two folders that both contain a `book.mobi` do not overwrite each other - the second becomes `book-2.epub`. Past 192 MB of converted EPUBs the archive would have to be built in memory to be uploaded, so it is skipped and `OUTPUT` becomes a `MANIFEST.json` listing every record and its URL instead.

Either way the dataset holds **one record per source file** - title, author, source format, MOBI version, file sizes, conversion time and download URL, and for a book that failed, `ok: false`, the reason, and whether the reason was DRM.

### How much does it cost to convert MOBI to EPUB?

| Book | Source size | Run time | Cost |
|---|---|---|---|
| Alice's Adventures in Wonderland | 190 kB | 25 s | $0.0030 |
| Frankenstein | 449 kB | 20 s | $0.0024 |
| Pride and Prejudice | 540 kB | 20 s | $0.0024 |
| Moby Dick | 936 kB | 38 s | $0.0043 |
| Complete Works of Shakespeare | 4.1 MB | 665 s | $0.0740 |

Measured on real books from Project Gutenberg at 2048 MB; the dollar figures depend on your plan.

**An ordinary novel costs a fraction of a cent**, and Apify's [free plan](https://apify.com/pricing) includes $5 of usage a month, so a personal library converts for nothing.

#### Is it cheaper to convert a whole library in one run?

Yes. Converting a novel takes 2 to 6 seconds inside a run lasting 20 to 38 seconds - the rest is container startup, paid once per run rather than once per book. A library converted one book per run pays that startup every time; the same library as one batch pays it once.

That saving is arithmetic from the table above rather than a measured batch run.

#### Large omnibus files

The exception. The Complete Works of Shakespeare took 632 seconds of conversion at 2048 MB, and at 1024 MB it did not finish inside the 15 minute timeout at all. Raise the memory for files that size, use the asynchronous endpoint (anything over 300 seconds outlasts `run-sync`), and give it a run of its own - it also outlasts the five minutes a batch allows each book.

### How to convert MOBI to EPUB with the API

`run-sync` returns the EPUB in the response body:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/marcel-rbro~mobi-to-epub/run-sync?token=<TOKEN>" \
  -H 'Content-Type: application/json' \
  -d '{"file": "https://example.com/book.mobi"}' \
  --output book.epub
```

If you hold the bytes rather than a URL, pass them as base64 in `fileBase64`. The Apify API requires Actor input to be `application/json`, so posting the ebook as a raw request body is rejected with HTTP 400 before the run starts:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/marcel-rbro~mobi-to-epub/run-sync?token=<TOKEN>" \
  -H 'Content-Type: application/json' \
  -d "{\"fileBase64\": \"$(base64 < book.mobi)\", \"filename\": \"book.mobi\"}" \
  --output book.epub
```

Base64 adds about a third to the payload, so prefer a URL for large files.

For several books, pass `files` and call the asynchronous [Run Actor](https://docs.apify.com/api/v2/act-runs-post) endpoint - a batch takes longer than the 300 seconds `run-sync` waits, so `run-sync` would time out on the request while the run carried on converting:

```bash
curl -X POST \
  "https://api.apify.com/v2/acts/marcel-rbro~mobi-to-epub/runs?token=<TOKEN>" \
  -H 'Content-Type: application/json' \
  -d '{"files": ["https://example.com/one.mobi", "https://example.com/two.azw3"]}'
```

That returns a run ID to poll. When the run finishes, `OUTPUT` in its key-value store is `epubs.zip`, and the dataset has a record per book.

`run-sync` waits up to 300 seconds. Use the asynchronous endpoint for anything larger. There are [client libraries for JavaScript and Python](https://docs.apify.com/api/client), and the same run can be triggered on a schedule or from Zapier, Make, n8n, Slack or an MCP client.

### Limitations

- **DRM-protected files cannot be converted.** The encryption flag is read from the MOBI header, so the failure is a plain sentence rather than a calibre stack trace. Most `.azw` and `.mobi` files bought from Amazon are protected. In a batch the protected book is skipped and the rest of the library converts; on its own it fails the run. Removing that DRM is out of scope.
- **No KFX output.** It requires Kindle Previewer, which Amazon ships for Windows and macOS only. Send the EPUB to your Kindle and let Amazon convert it.
- **Badly built MOBI files produce badly built EPUB files.** Turn on `verboseLog` to see what calibre reports.
- **100 books, 200 MB of source files and 100 MB per book in one run.** Past any of those the run says which limit it hit and what to split. A library larger than that is several runs.
- **A batch gives each book five minutes and the whole run 30 minutes of conversion time.** A book converted on its own keeps the full 15 minutes, which is why an omnibus belongs in a run of its own. Books left when the run's budget is gone are recorded as unconverted rather than silently dropped.
- **Batches need the asynchronous endpoint.** Almost any batch runs longer than the 300 seconds `run-sync` waits for.

### Other file converters

| Actor | Converts | Use it for |
|---|---|---|
| **MOBI to EPUB converter** (this one) | MOBI, PRC, AZW, AZW3 → EPUB | Kindle ebooks |
| [HEIC to JPG converter](https://apify.com/marcel-rbro/heic-to-jpg) | HEIC, HEIF, AVIF → JPEG, PNG, WebP, AVIF, TIFF | **iPhone photos**, bursts and Live Photo stills |
| [PNG to JPG converter](https://apify.com/marcel-rbro/png-to-jpg) | PNG, JPG, JFIF, WebP, AVIF, BMP, TIFF, GIF → JPEG, PNG, WebP, AVIF, TIFF, BMP | Web and desktop image formats |
| [PDF to JPG converter](https://apify.com/marcel-rbro/pdf-to-jpg) | PDF → JPEG, PNG, WebP, TIFF | Turning pages into images |
| [JPG to PDF converter](https://apify.com/marcel-rbro/jpg-to-pdf) | JPEG, PNG, WebP, TIFF, HEIC → PDF | Turning images into a document |
| [Word to PDF converter](https://apify.com/marcel-rbro/word-to-pdf) | Word, Excel, PowerPoint, OpenDocument, RTF → PDF | Office documents |
| [EPUB to PDF converter](https://apify.com/marcel-rbro/epub-to-pdf) | EPUB, AZW3, MOBI, FB2, CBZ → PDF | Ebooks for printing |

### FAQ

#### Is this MOBI to EPUB converter free?

Apify's free plan includes $5 of platform usage per month and needs no card. At a fraction of a cent per novel, that is more books than most people own.

#### Why convert MOBI to EPUB at all?

Because MOBI is retired. Amazon stopped accepting it in the Kindle Store in 2021, and Send to Kindle stopped delivering it in August 2022. Kobo, Apple Books, Google Play Books and most open readers never took MOBI in the first place. EPUB is the format all of them accept.

#### Can I convert a whole folder of ebooks at once?

Yes, and it is the cheaper way to use this Actor. Upload up to 100 files in the **Ebooks** field, or pass an array of URLs in `files`. Each book is converted separately, the EPUBs come back as one `epubs.zip`, and the dataset gets a record per book. Because most of a short run is container startup rather than conversion, a hundred books in one run costs a fraction of a hundred runs of one book. Use the asynchronous API endpoint: a batch outlasts the 300 second `run-sync` window.

#### Can I convert a Kindle book I bought from Amazon?

Only if it is DRM-free, which most purchases are not. The Actor reads the encryption flag in the MOBI header and reports it rather than producing a broken file. In a batch that is not fatal: the protected book gets a dataset record saying so, every other book in the folder still converts, and the log ends with how many of the failures were DRM - which is the number worth knowing when you point this at a mixed library. Stripping Amazon's DRM is out of scope for this Actor.

#### EPUB 2 or EPUB 3?

EPUB 3 unless you have a specific reason. It is what Send to Kindle, Kobo and Apple Books expect. Choose EPUB 2 for old hardware readers that predate the standard.

#### Will the formatting survive?

Mostly. AZW3 converts cleanly because it carries real CSS. Old MOBI is built on an HTML 3.2 subset, so complex layouts, tables and footnotes can come through simplified - the conversion cannot invent structure the source never had.

#### Does it keep the cover and the table of contents?

Yes. calibre carries the cover image and the navigation structure into the EPUB, and the run's dataset record reports the metadata it found.

#### Can an AI agent call this converter?

Yes. Every Apify Actor is exposed through the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp), so Claude, Cursor and other MCP clients can run this conversion as a tool.

#### The conversion failed. What now?

Turn on `verboseLog` and re-run: the Actor log will carry calibre's own output. The common causes are a DRM-protected file, a URL that returns an HTML page rather than the ebook, and an omnibus large enough to hit the conversion timeout at low memory. In a batch, find the book in the dataset - each row carries its own `error` - rather than reading the whole log.

### Development

```bash
npm install
npm test      # MOBI header inspector, ZIP writer and batch bookkeeping, no calibre needed
apify run     # needs calibre on your PATH
```

Conversion runs calibre's `ebook-convert` in a Debian container. This Actor's code is MIT licensed; calibre is GPL-3 and runs as a separate process - see [THIRD\_PARTY\_NOTICES.md](THIRD_PARTY_NOTICES.md).

# Actor input Schema

## `files` (type: `array`):

The ebooks to convert. Upload files or paste direct URLs - up to 100 per run. Each one is converted separately and the results come back as a single ZIP. Accepts .mobi, .prc, .azw and .azw3. DRM-protected books cannot be converted: in a batch they are skipped and reported, and the rest of the run carries on.

## `file` (type: `string`):

Alias for a single-book run, kept so existing API callers and saved input configurations keep working. Pass one URL. Ignored when Ebooks is filled in.

## `epubVersion` (type: `string`):

EPUB 3 is what Amazon's Send to Kindle, Kobo and Apple Books expect. Choose EPUB 2 only for old readers. Applies to every book in the run.

## `outputFilename` (type: `string`):

Name of the resulting file. Defaults to the input filename with an .epub extension. Applies to a single book only - in a batch it is ignored, each EPUB keeps its own filename and the archive is called epubs.zip.

## `bookTitle` (type: `string`):

Sets the title metadata of the EPUB. Leave empty to keep the title stored in the source file. Ignored when converting more than one book, since it would stamp the same title onto all of them.

## `bookAuthors` (type: `string`):

Sets the author metadata of the EPUB. Separate multiple authors with an ampersand, for example "Ursula K. Le Guin & Someone Else". Ignored when converting more than one book.

## `smartenPunctuation` (type: `boolean`):

Converts plain quotes, dashes and ellipses into their typographic equivalents.

## `fileBase64` (type: `string`):

Alternative to the file field for API callers: a single source file encoded as base64. Adds about 33% to the payload size.

## `filename` (type: `string`):

Original filename to use when the file is passed as base64.

## `filesBase64` (type: `array`):

The batch equivalent of "fileBase64": an array of { "filename": "book.mobi", "data": "<base64>" } objects, or of bare base64 strings. Prefer URLs for anything large.

## `verboseLog` (type: `boolean`):

Includes the full calibre conversion log in the Actor log. Useful when a conversion produces odd output.

## Actor input object example

```json
{
  "epubVersion": "3",
  "smartenPunctuation": false,
  "verboseLog": false
}
```

# Actor output Schema

## `epubFile` (type: `string`):

One converted EPUB, or a ZIP of all of them when the run converted more than one book. This is the same record that the run-sync API endpoint returns in its HTTP response body.

## `allFiles` (type: `string`):

Every record in the run's key-value store, including each converted EPUB under its own filename.

## `conversionDetails` (type: `string`):

One record per source file: source format, MOBI version, file sizes, ebook metadata, download URLs, and the reason for any book that failed.

# 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("marcel-rbro/mobi-to-epub").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("marcel-rbro/mobi-to-epub").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 marcel-rbro/mobi-to-epub --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,marcel-rbro/mobi-to-epub"
        }
    }
}

```

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/VKk5msDfXdi2pLiuO/builds/YDkPZf2CAobEyWkmg/openapi.json
