Skip to content

Repository files navigation

Serverless URL shortener using Firebase RTDB:

A lightweight URL shortener API built with Wrangler and Firebase Realtime Database.

This project is intended for personal use and small-scale deployments, and runs with minimal resource usage.

Deploy your own instance using the button below:

Deploy to Cloudflare

🚀 Key features:

  • Rate limiting: daily request quotas and burst traffic protection (anti-spam).

  • No duplicates: prevents storing identical URLs, saving database space.

  • No sign-up: no account creation, credit card, or personal data required.

  • GDPR compliant: built with privacy in mind.

  • Highly configurable: customize behavior to your needs.

  • Firebase backend: stores URL mappings in Firebase Realtime Database.

  • Minimal REST API: fast, efficient, and lightweight.

  • Serverless: runs on Cloudflare Workers free plan with strict resource limits.

🌐 API access:

EndpointRate limitMaintainerPrivacy
https://nsh.nde-code.workers.dev/1 req/IP/sec, 10 new links/IP/dayMeprivacy.md

CORS is enabled only for the URL-posting endpoint, for clear security reasons.

Check the status page if you experience latency or other issues while using my public online instance.

Notes:

  • Feel free to use my public instance, but be aware of the limits.

  • Keep an eye on the repository to catch any changes to these limits.

  • The Firebase RTDB database is located in Belgium on my public instance, so users from distant countries may experience some latency.

  • I've enabled Smart Placement routing for a better experience.

📚 Available endpoints:

In this section, I've used https://your-worker.org.workers.dev/ in the cURL command examples. If you've deployed your own instance of the project, replace it with your instance's domain. Otherwise, use my free public instance at https://nsh.nde-code.workers.dev/, as explained above.

1. [POST]/post-url - Create short URL:

Create a short URL from a long URL. Saves to database and applies rate limiting.

Request body:

FieldTypeDescription
long_urlstringRequired. Original URL to shorten (must be valid)

Note: request fails if JSON contains unexpected fields or URL exceeds max length.

Response codes:

CodeDescription
201URL successfully shortened and saved
200URL already shortened previously (returns existing short link)
400Invalid body, missing long_url, unexpected field, or invalid URL
409Hash collision (different URL, same hash)
429Rate limit exceeded (time-based or daily write limit)
500Server error (config, environment, or generation failure)
503KV quota exceeded or database read failure
507Firebase entry limit reached

Example request:

curl -X POST "https://your-worker.org.workers.dev/post-url" \
-H "Content-Type: application/json" \
-d '{"long_url": "https://nde-code.github.io/"}'

Example response:

{
"success": "https://your-worker.org.workers.dev/url/11i7yev0000000"
}

2. [GET]/url/:code - Redirect to original URL:

Redirect to the original long URL using the short code.

Path parameters:

ParameterTypeDescription
codestringRequired. Unique short ID

Response codes:

CodeDescription
301Permanent redirect (verified link)
302Temporary redirect (unverified link)
400No valid ID in path
404Link not found in database
500Server error
503Request timeout or storage connection failure

Example request:

curl -i "https://your-worker.org.workers.dev/url/11i7yev0000000"

3. [GET]/urls - List all URLs:

Retrieve a paginated list of shortened links.

Security: requires valid admin key (see authentication).

Query parameters:

ParameterTypeDescription
countnumberNumber of links to retrieve (default: config value, max: restricted)
cursorstringLast item key from previous page (use next_cursor from response)

Response codes:

CodeDescription
200Successfully returned URLs
400Invalid count or cursor parameter
401Invalid or missing API key
429Rate limit exceeded
500Server error
503Database retrieval failure

Example request:

curl "https://your-worker.org.workers.dev/urls?count=2" \
-H "x-api-key: YOUR_ADMIN_KEY"

Example response:

{
"urls": {
"11i7yev0000000": {
"long_url": "https://nde-code.github.io/",
"post_date": "2024-05-12T10:00:00.000Z",
"is_verified": true
},
"vgsyqs00000000": {
"long_url": "https://www.google.com/",
"post_date": "2024-05-12T11:30:00.000Z",
"is_verified": false
}
},
"next_cursor": "vgsyqs00000000",
"has_more": true
}

4. [PATCH]/verify/:code - Verify URL:

Mark a shortened URL as verified.

Security: requires valid admin key (see authentication).

Path parameters:

ParameterTypeDescription
codestringRequired. Unique short ID

Response codes:

CodeDescription
200Link verified successfully (or already verified)
400No valid ID in path
401Invalid or missing admin key
404Link not found
429Rate limit exceeded
500Server error
503Database update failure

Example request:

curl -X PATCH "https://your-worker.org.workers.dev/verify/11i7yev0000000" \
-H "x-api-key: YOUR_ADMIN_KEY"

5. [DELETE]/delete/:code - Delete URL:

Remove a shortened URL and decrement the counter.

Security: requires valid admin key (see authentication).

Path parameters:

ParameterTypeDescription
codestringRequired. Unique short ID

Response codes:

CodeDescription
200Link deleted successfully
400No valid ID in path
401Invalid or missing admin key
404Link not found
429Rate limit exceeded
500Server error
503Database deletion failure

Example request:

curl -X DELETE "https://your-worker.org.workers.dev/delete/11i7yev0000000" \
-H "x-api-key: YOUR_ADMIN_KEY"

6. [PATCH]/sync-counter - Resynchronize counter:

Recalculate and sync the metadata counter to match actual URLs in Firebase. Useful for fixing race conditions or desynchronization.

Security: requires valid admin or monitoring key (see authentication).

Note: the admin key can be used to manually resynchronize the counter when needed. The monitoring key is also accepted, allowing the endpoint to be called automatically by external monitoring tools (as with /health) or scheduled services.

Response codes:

CodeDescription
200Counter resynced successfully (returns new count)
401Invalid or missing admin key
429Rate limit exceeded
500Server error
503Database communication failure

Example request:

curl -X PATCH "https://your-worker.org.workers.dev/sync-counter" \
-H "x-api-key: YOUR_ADMIN_KEY"

Example response:

{
"success": "Counter synchronized successfully.",
"new_count": 42
}

7. [GET]/health - Service health check:

Check service health: configuration, database connectivity, counter integrity, capacity, and KV storage.

Security: requires valid monitoring key (see authentication).

Response codes:

CodeDescription
200All systems operational
206Degraded but operational (one or more non-critical issues)
503Service unavailable (critical failure)

Example request:

curl -X GET "https://your-worker.org.workers.dev/health" \
-H "x-api-key: YOUR_MONITORING_KEY"

Example response (Healthy):

{
"status": "healthy",
"timestamp": "2026-04-26T20:17:27.121Z",
"checks": {
"config_valid": true,
"firebase_reachable": true,
"counter_accessible": true,
"kv_store_available": true
},
"message": "All systems operational."
}

🔐 Authentication:

Protected endpoints require either header format:

  • Authorization: Bearer <MONITORING_or_ADMIN_KEY>
  • x-api-key: <MONITORING_or_ADMIN_KEY>

Note: trying to access the administration endpoints on my public instance is completely forbidden.

🖥️ Developer documentation:

For setup, configuration, and deployment using Wrangler CLI, see the developer guide.

⚖️ License:

This project is licensed under the Apache License v2.0.

🎯 Author:

Created and maintained by Nde-Code.

Don't hesitate to open an issue or a pull request if you have any questions or would like to contribute.

About

A serverless URL shortener API powered by Cloudflare Workers at the edge.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages