Skip to content

[FEAT] CORS support for browser-based API calls #3502

@jo-chemla

Description

@jo-chemla

Problem

Dub.co's API (e.g. POST https://api.dub.co/links) does not include Access-Control-Allow-Origin headers in its responses. The OPTIONS preflight returns 204 correctly, but the actual request is blocked by the browser's CORS policy, making it impossible to call the API directly from a frontend app without a server-side proxy.

This prevents pure frontend apps (SPAs, static sites, GitHub Pages, Netlify/Vercel no-function deploys) to generate shortlinks via dub without a CORS proxy

Use case

I've got a pure frontend app, terrain-viewer that generates dynamic geospatial visuals based on nuqs state passed as url query params. I want users to be able to capture canvas screenshot to share to social networks (done), and generate short linkq by calling POST /links via dub api key, to track which works best. The browser request to /links is currently blocked by CORS

Sibling issue I've opened #3503: it would be great to allow passing the thumbnail / og:media metadata image as base64 rather than url, to store it for a given duration like 10mins, for social media / messaging apps crawlers to get the thumb for a pure client-side app.

Dub.co is the only link shortener with first-class og:image support per link. This makes it uniquely suited for frontend apps that generate dynamic social previews. CORS support would unlock this use case entirely from the browser — no backend, no proxy, no infrastructure. It would make Dub.co the go-to solution for a whole class of creative and generative frontend apps.

Proposed solutions by Claude:

Option A — Add CORS headers to the existing API

Allow callers to pass an Origin allowlist in their Dub project settings. When a request arrives from a matching origin, include:

Access-Control-Allow-Origin: https://your-app.com
Access-Control-Allow-Methods: POST, OPTIONS
Access-Control-Allow-Headers: Content-Type, Authorization

This is the simplest fix and mirrors how Stripe, Cloudinary, and other developer-first APIs handle browser clients.

Option B — A dedicated lightweight browser-safe endpoint

A scoped endpoint like POST https://api.dub.co/browser/shorten that:

  • Accepts { url, image, title, description }
  • Is CORS-enabled
  • Is rate-limited per API key or per origin domain (to mitigate abuse)
  • Supports the same og:image field as POST /links

This keeps the main API server-only while offering a deliberately limited, browser-safe surface.

Option C — Origin-restricted publishable keys

Similar to Stripe's publishable/secret key split: a separate key type that is safe to embed in frontend code, restricted to a set of allowed origins configured in the Dub dashboard. The key can only create links (no read/delete), and only from whitelisted domains.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions