Sniper Link

A free tool from Buttondown, the best way to run your newsletter.

Back to Sniper Link



Sniper Link streamlines email confirmation. Once a user provides their email, they can be shown a button that sends them directly to their respective inbox, filtered down to the given sender and bypassing the spam folder.

For support, email

Table of Contents

Basic usage

Sniper Link can be easily integrated into your app using the provided script and HTML tag:


<script src="" defer></script>


  • recipient: The email address of the person expected to confirm their email.
  • sender: The email address from which the confirmation is sent.

Custom styling

The Sniper Link button is designed to be customized using CSS. There are four parts to the button:

  • container: A wrapper that holds the entire button.
  • button: The clickable element.
  • image: A logo representing the email provider.
  • text: A label, by default showing “Open in {provider}”.

You can use the ::part CSS selector to override the default styles:

sniper-link::part(container) {
  width: 100%;

sniper-link::part(button) {
  background-color: darkorange;
  justify-content: center;
  border-radius: 99px;

sniper-link::part(image) {
  background-color: white;
  padding: 1px 3px;
  border-radius: 4px;
  box-shadow: 0 0 4px hsla(0, 0%, 0%, 0.1);

sniper-link::part(text) {
  color: white;
  text-shadow: 0 0 4px hsla(0, 0%, 0%, 0.2);

Custom label text

The default text on the Sniper Link button is “Open in {provider}”, but you can change it using the template attribute:

Code Example:

  template="Confirm email using {provider}"

Unrecognized providers

We’re working on supporting as many providers as possible. Currently, we support Gmail, Yahoo, Proton, iCloud, Outlook, HEY, AOL, and, and we’re adding additional ones. Let us know ( if there’s a provider you’d like us to add!

When the email provider cannot be determined, the sniper-linkelement will have a hidden attribute. This attribute can be used for styling the button or the adjacent elements.

Usage with an HTML Buttondown form

Sniper Link can be used with Buttondown’s custom HTML subscribe forms, using a bit of extra JavaScript. Here’s an example:

<form id="buttondown-form">
  <label for="email">Email address</label>
  <input name="email" id="email" type="email" required />

  <p id="error"></p>


<div id="sniper-link-container" style="display: none">
  <sniper-link recipient="" sender="" />

<script src="" defer></script>

  const bdform = document.querySelector("#buttondown-form");
  bdform.addEventListener("submit", (e) => {

    const formData = new FormData(;

    fetch("", {
      method: "POST",
      body: formData,
      headers: {
        Accept: "application/json",
    }).then(async (response) => {
      if (!response.ok) {
        document.querySelector("#buttondown-form #error").innerText =
          await response.text();

      const sl = document.querySelector("sniper-link");
      sl.setAttribute("recipient", formData.get("email"));

      const slContainer = document.querySelector("#sniper-link-container"); = "block"; = "none";

Advanced: Usage via the API

If you want to create your own custom button, you can directly depend on our API to construct it:


It’s useful to do this API call from the frontend, because the endpoint also relies on the User-Agent to determine whether the device is desktop, iOS, or Android.

Ideally, the response will look like this:

  "url": "https://...",
  "image": "",
  "provider_pretty": "Gmail"

If the provider cannot be recognized, you’ll receive a `404` error:

// Status: 404
  "code": "unknown_email_provider",
  "detail": "Unknown email provider for",
  "metadata": {
    "recipient": ""

We handle the DNS lookup, parsing, and caching, so this endpoint stays fast.

Behind the scenes

  • First we check whether the domain of the email address is obvious (i.e. it ends in or similar).
  • If the domain is not obvious, we do a DNS lookup to try to determine what email provider is being used for the domain.
  • Then, we determine the user’s platform (desktop, iOS, or Android) in order to provide the best possible URL for their provider and platform.
  • Finally, we serve the detected provider and URL to the user via the <sniper-link> component or API response.