Making a self-hosted alternative to Apple's Hide My Email service

Published on

Chapter 1: Apple and Hide My Email

I'm a big fan of Apple's Hide My Email feature in iCloud. It's a pretty niche feature—no one I know really uses it—but I find myself constantly creating anonymous aliases.

The biggest chunk of these aliases gets used when I sign up for accounts to explore the inner workings and design of new products or startups.

And as you know, once they have your email, you're hooked for life. One way or another, whether you unsubscribe or not, they'll keep sending you something until your (or their) last day.

The main issue with Apple's service boils down to how slow and clunky it is. Ideally, you'd want email aliases generated seamlessly during website sign-up, similar to how password managers generate passwords on the fly. With Apple, you have to navigate through Settings → iCloud → Hide My Email—which is suboptimal, to say the least. And if you're on Windows or don't use Apple devices, you're completely out of luck.

Chapter 2: Cloudflare

I've been a heavy user of Cloudflare since the "early" days—for around 10 years now.

It offers a lot of powerful tools and services, but they are very developer-oriented, and many of them feel like they have been added only to grow the market offering—they are very rough and stay that way forever.

A good example of this is Cloudflare Pages—a great way to host your static, React, Next.js, or other type of app. But it comes with a catch—the UI to manage it is basically non-existent, and the setup and configuration process is, for some reason, way more complicated than it should be in 2025.

This brings us to Cloudflare Email Routing—a feature you can easily miss when setting up your domain and DNS. It allows you to create custom addresses for your domain and route incoming emails to your preferred inbox. You can set them up in their dashboard or via the API.

Doing this via the dashboard is even less convenient than Apple's Hide My Email, and the API—you guessed it—is not even an option for this use case.

We need something fast, simple, and easy to use that should always be easily available when you sign up on any website.

Chapter 3: Making an easy to use product

We have a vision—a fast and simple service that creates anonymous addresses to forward mail to your inbox. And we have a tool—a powerful API for email routing from Cloudflare. Time to make it into a nice, user-friendly product.

Our product will be a Chrome extension—always 1 click away during a sign-up flow.

Next, we need to define UI and UX. We will make it as simple as possible.

  • Main screen

    • As soon as you open the app, you should be able to see a list of your email aliases.
    • The most common action here is copying the address of your alias—users must be able to do this in 1 click without opening any menus. So that's exactly what we will do—when you click on any alias in the list, the email will be copied to the clipboard.
    • Users may want to edit or delete an alias, but this is an infrequent action and not a primary one. So we will show the edit button only when you hover over the item; otherwise, you don't see it.
    • And, of course, there must be a button to create a new address.
  • Create New Address screen

    • The only input we need from the user here is a label for this address.
    • A create button that will create an alias—and, of course, copy the created address to the clipboard right away. No need to make the user click it again.
  • Settings screen

    • A necessary evil. It must be as simple as possible, but due to the complexity of the Cloudflare API, users will need to input a few fields here.
    • This screen must be shown to the user automatically if the extension hasn't been configured (as soon as they open the app after installing it).

After adding some views for this straight in React, I ended up with something like this.

App Screenshot

Chapter 4: The Hard Part

Now we actually need to make it work—add the Cloudflare API to all this, make sure it works—and works fast.

Turns out, the latter part is tricky. When you add a new routing rule, Cloudflare takes its time (around 60 seconds or more) to propagate changes to DNS and make your new email work. During this time, your routing status is "Syncing" and you can't use that address. Don't get me wrong—this is very fast in terms of what it does, but for our particular use case it is a hard no-go.

But what if we don't create a new address when the user wants to create one? We could just allocate it—pick one from already created beforehand—and slap a label on top of it.

In this case, as soon as the user completes setting up our app, we will generate the maximum addresses right away. They will sync in 60 seconds or so and will be ready to use any time the user needs one!

There's a tiny issue here though—we need to know what addresses are already in use and what are free. We could store this information in the extension's local storage—but that would make it stateful, and when you install it in another browser or after it is deleted, all info will be gone. This is suboptimal, to say the least. We also don't want to introduce a backend for it, as this is supposed to be an OSS app that anyone can download and install.

After going through the API docs, I noticed that the Routing Rule object has a Name attribute—you can't see or edit it in the Cloudflare dashboard, but you can set it via API when creating a routing rule. That's all we need to make it work! We will use it to encode a bunch of data in our custom little format.

Its max length is 256 characters, which should be enough.

We will need to:

  • Differentiate rules that have been created using our app
  • Store label name
  • Store created-at date so we can properly sort addresses
  • Possibly store short description as name may be insufficient for some use cases

The final format of the Name field looks like this:

`${APP_PREFIX}${SEPARATOR}${TIMESTAMP}${SEPARATOR}${rule_name}${SEPARATOR}${rule_desc || EMPTY_LABEL}`,

Chapter 5: Conclusion

With all pieces in place, I threw together a Chrome extension with everything described above.

And that's it! Our own Hide My Email service:

  • Right in the browser where we use it most
  • New address is created in a few seconds, much faster than Apple's version
  • We can use our own domain, no vendor lock-in

The source is fully available under MIT license on GitHub or you can install it straight from the Chrome Store.