YOURLS: Your Own URL Shortener
Simple, powerful URL shortener. Custom domains, plugins, and statistics.
Introduction
Since 2009, YOURLS (Your Own URL Shortener) has been the go-to open-source solution for self-hosted URL shortening. While newer alternatives have emerged with flashy interfaces and modern architectures, YOURLS remains beloved by the homelab community for its simplicity, stability, extensive plugin ecosystem, and battle-tested reliability. If you want a “set it and forget it” URL shortener that just works, YOURLS is your answer.
YOURLS is written in PHP and uses MySQL/MariaDB for storage, making it lightweight and easy to deploy on virtually any hosting environment. Its plugin architecture allows extensive customization, from QR code generation to advanced analytics, password-protected links, and API integrations. Whether you’re shortening personal links, managing a marketing campaign, or building a URL shortener into your application, YOURLS provides a proven foundation.
What you’ll learn:
- Deploy YOURLS with Docker Compose in 15 minutes
- Configure custom domains and branded short links
- Use the admin interface and bookmarklets for quick shortening
- Leverage the API for programmatic URL management
- Install essential plugins for enhanced functionality
- Set up private vs. public URL shortening modes
- Implement analytics and tracking
- Configure browser bookmarklets for one-click shortening
Prerequisites:
- Docker and Docker Compose installed
- Basic understanding of Docker containers
- A domain name (optional, recommended for custom short URLs)
- 256MB+ RAM available
- Basic familiarity with PHP applications
Why Choose YOURLS?
The Classic URL Shortener
YOURLS occupies a unique position in the self-hosted ecosystem:
Advantages:
- Mature and stable: 15+ years of development and bug fixes
- Huge plugin ecosystem: 100+ plugins for every need
- Simple architecture: PHP + MySQL = runs anywhere
- Low resource usage: Runs on minimal hardware
- Active community: Large user base and extensive documentation
- Custom keywords: Create memorable short URLs like
/docsor/blog
Trade-offs:
- Older codebase: Traditional PHP architecture vs. modern frameworks
- Basic UI: Functional but not as polished as newer alternatives
- Manual plugin management: No built-in plugin installer
- Limited built-in analytics: Requires plugins for advanced tracking
YOURLS vs. Shlink
| Feature | YOURLS | Shlink |
|---|---|---|
| First Release | 2009 | 2016 |
| Language | PHP | PHP |
| Database | MySQL/MariaDB | Multiple (PostgreSQL, MySQL, SQLite) |
| UI | Traditional admin panel | Modern REST API + web client |
| Plugins | 100+ community plugins | Limited plugin ecosystem |
| Built-in Analytics | Basic | Advanced with geolocation |
| API | XML-RPC/JSON | RESTful API |
| Best For | Plugin customization, custom keywords | Modern integrations, detailed analytics |
Choose YOURLS if:
- You want extensive customization via plugins
- You need custom memorable keywords
- You prefer traditional PHP applications
- You have existing YOURLS integrations
Choose Shlink if:
- You want built-in advanced analytics
- You need modern REST API
- You prefer containerized microservices
- You want real-time visit tracking
Installation: Docker Compose Method
Step 1: Create Project Directory
mkdir -p ~/yourls
cd ~/yourls Step 2: Create docker-compose.yml
This configuration deploys YOURLS with MySQL database:
version: '3.8'
services:
yourls:
image: yourls:latest
container_name: yourls
restart: always
ports:
- "8080:80"
environment:
YOURLS_DB_HOST: mysql
YOURLS_DB_USER: yourls
YOURLS_DB_PASS: secure_password_here
YOURLS_DB_NAME: yourls
YOURLS_SITE: https://go.yourdomain.com
YOURLS_USER: admin
YOURLS_PASS: strong_admin_password_here
# Generate unique random strings for these
YOURLS_UNIQUE_URLS: "true"
YOURLS_COOKIEKEY: "change_this_to_random_string_32_chars"
# Optional: Hours to keep login cookie valid
YOURLS_HOURS: "24"
volumes:
- ./plugins:/var/www/html/user/plugins
- ./pages:/var/www/html/user/pages
depends_on:
- mysql
networks:
- yourls-net
mysql:
image: mysql:8
container_name: yourls-db
restart: always
environment:
MYSQL_ROOT_PASSWORD: root_password_here
MYSQL_DATABASE: yourls
MYSQL_USER: yourls
MYSQL_PASSWORD: secure_password_here
volumes:
- ./data/mysql:/var/lib/mysql
networks:
- yourls-net
command: --default-authentication-plugin=mysql_native_password
networks:
yourls-net:
driver: bridge Configuration notes:
YOURLS_SITE: Your short URL domain (include https://)YOURLS_USER/PASS: Admin credentials for loginYOURLS_COOKIEKEY: Random string for session securityYOURLS_UNIQUE_URLS: Prevents duplicate short URLs for same long URL- Volumes mount plugin and page directories for persistence
Step 3: Generate Secure Credentials
# Generate random cookiekey (32 characters)
openssl rand -base64 32
# Update docker-compose.yml with secure values
sed -i 's/secure_password_here/YOUR_DB_PASSWORD/g' docker-compose.yml
sed -i 's/root_password_here/YOUR_ROOT_PASSWORD/g' docker-compose.yml
sed -i 's/strong_admin_password_here/YOUR_ADMIN_PASSWORD/g' docker-compose.yml
sed -i "s/change_this_to_random_string_32_chars/$(openssl rand -base64 32)/g" docker-compose.yml
# Set file permissions
chmod 600 docker-compose.yml Step 4: Create Plugin and Pages Directories
mkdir -p plugins pages Step 5: Start Services
docker compose up -d Step 6: Verify Installation
# Check containers are running
docker ps | grep yourls
# View logs
docker logs yourls
docker logs yourls-db
# Test web interface
curl -I http://localhost:8080 Step 7: Access Admin Interface
Navigate to: http://YOUR_SERVER_IP:8080/admin/
Login credentials:
- Username: admin (or whatever you set in
YOURLS_USER) - Password: Your
YOURLS_PASSvalue
You should see the YOURLS admin dashboard with statistics and quick URL shortening form.
Initial Configuration
Admin Dashboard Overview
The YOURLS admin interface provides:
Main Tools (top tabs):
- Add: Quick URL shortening form
- List URLs: View all shortened URLs
- Plugins: Manage installed plugins
- Tools: Statistics, bookmarklets, API info
Statistics dashboard:
- Total clicks
- Total shortened URLs
- Recent short URLs
- Most popular links
Create Your First Short URL
Method 1: Admin Interface
- Navigate to admin panel
- Click “Add new URL” or use quick form at top
- Enter details:
- Long URL:
https://www.example.com/very/long/path/to/page - Custom keyword (optional):
example-page - Title: Example Page (for reference)
- Long URL:
- Click “Shorten”
Result: Short URL created instantly. If no custom keyword provided, random short code generated.
Method 2: Bookmarklet (setup below)
Drag bookmarklet to browser toolbar, click while on any page to instantly shorten current URL.
Custom Domain Setup
Use your own domain for branded short links.
DNS Configuration
Add DNS record for your short domain:
Type: A
Name: go.yourdomain.com
Value: YOUR_SERVER_IP
TTL: 3600 Or for Cloudflare users:
Type: A
Name: go
Value: YOUR_SERVER_IP
TTL: Auto
Proxy status: Proxied (orange cloud) Reverse Proxy Configuration
Caddy (recommended):
# /etc/caddy/Caddyfile
go.yourdomain.com {
reverse_proxy localhost:8080
encode gzip
} sudo systemctl reload caddy Nginx:
# /etc/nginx/sites-available/yourls
server {
server_name go.yourdomain.com;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Optional: Restrict admin access to local network
location /admin/ {
allow 192.168.1.0/24;
deny all;
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
listen 443 ssl http2;
ssl_certificate /etc/letsencrypt/live/go.yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/go.yourdomain.com/privkey.pem;
}
server {
listen 80;
server_name go.yourdomain.com;
return 301 https://$server_name$request_uri;
} sudo ln -s /etc/nginx/sites-available/yourls /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx Update YOURLS Configuration
After setting up custom domain, update docker-compose.yml:
environment:
YOURLS_SITE: https://go.yourdomain.com Restart container:
docker compose restart yourls API Usage
YOURLS provides a JSON API for programmatic access.
Generate API Signature
Option 1: Use username/password (less secure)
Every API request includes &username=admin&password=yourpass
Option 2: Use secret signature (recommended)
- Navigate to:
http://go.yourdomain.com/admin/tools.php - Find “Passwordless API” section
- Copy your secret signature (looks like:
a1b2c3d4e5)
API Examples
Shorten URL:
# With signature
curl "http://go.yourdomain.com/yourls-api.php?signature=YOUR_SIGNATURE&action=shorturl&url=https://example.com&format=json"
# With username/password
curl "http://go.yourdomain.com/yourls-api.php?username=admin&password=yourpass&action=shorturl&url=https://example.com&format=json" Response:
{
"url": {
"keyword": "abc12",
"url": "https://example.com",
"title": "Example Domain",
"date": "2025-01-15 10:30:45",
"ip": "192.168.1.100"
},
"status": "success",
"message": "https://example.com added to database",
"title": "Example Domain",
"shorturl": "https://go.yourdomain.com/abc12",
"statusCode": 200
} Shorten with Custom Keyword:
curl "http://go.yourdomain.com/yourls-api.php?signature=YOUR_SIGNATURE&action=shorturl&url=https://github.com/YOURLS/YOURLS&keyword=gh-yourls&format=json" Get URL Stats:
curl "http://go.yourdomain.com/yourls-api.php?signature=YOUR_SIGNATURE&action=url-stats&shorturl=abc12&format=json" Response:
{
"statusCode": 200,
"message": "success",
"link": {
"shorturl": "https://go.yourdomain.com/abc12",
"url": "https://example.com",
"title": "Example Domain",
"timestamp": "2025-01-15 10:30:45",
"ip": "192.168.1.100",
"clicks": 42
}
} Get Database Stats:
curl "http://go.yourdomain.com/yourls-api.php?signature=YOUR_SIGNATURE&action=stats&format=json" Expand Short URL:
curl "http://go.yourdomain.com/yourls-api.php?signature=YOUR_SIGNATURE&action=expand&shorturl=abc12&format=json" Python API Wrapper
import requests
from urllib.parse import urljoin
class YourlsAPI:
def __init__(self, base_url, signature):
self.base_url = base_url.rstrip('/')
self.api_endpoint = urljoin(self.base_url, '/yourls-api.php')
self.signature = signature
def _request(self, action, **params):
"""Make API request"""
params['signature'] = self.signature
params['action'] = action
params['format'] = 'json'
response = requests.get(self.api_endpoint, params=params)
return response.json()
def shorten(self, url, keyword=None, title=None):
"""Shorten a URL"""
params = {'url': url}
if keyword:
params['keyword'] = keyword
if title:
params['title'] = title
return self._request('shorturl', **params)
def stats(self, shorturl):
"""Get statistics for short URL"""
return self._request('url-stats', shorturl=shorturl)
def expand(self, shorturl):
"""Get original URL from short URL"""
return self._request('expand', shorturl=shorturl)
def db_stats(self):
"""Get database statistics"""
return self._request('stats')
# Usage example
yourls = YourlsAPI('https://go.yourdomain.com', 'YOUR_SIGNATURE')
# Create short URL
result = yourls.shorten('https://example.com/long-url', keyword='my-link')
print(f"Short URL: {result['shorturl']}")
print(f"Status: {result['status']}")
# Get statistics
stats = yourls.stats('my-link')
print(f"Clicks: {stats['link']['clicks']}")
# Get database stats
db_stats = yourls.db_stats()
print(f"Total URLs: {db_stats['stats']['total_links']}")
print(f"Total clicks: {db_stats['stats']['total_clicks']}") Essential Plugins
YOURLS’ plugin ecosystem is its superpower. Here are must-have plugins:
Installing Plugins
cd ~/yourls/plugins
# Download plugin (example: QR Code plugin)
git clone https://github.com/plugin-author/yourls-plugin-name.git
# Or download ZIP and extract
wget https://github.com/author/plugin/archive/main.zip
unzip main.zip
rm main.zip After adding plugins, activate them:
- Navigate to admin panel
- Click “Plugins” tab
- Click “Activate” next to plugin name
Top 10 Essential Plugins
1. QR Code Generator
- Plugin:
yourls-qrcode - URL: https://github.com/seandrickson/YOURLS-QRCode-Plugin
- Features: Adds QR code for every short URL
Install:
cd ~/yourls/plugins
git clone https://github.com/seandrickson/YOURLS-QRCode-Plugin.git qrcode Usage: Access QR code at https://go.yourdomain.com/abc12+
2. Advanced Analytics
- Plugin:
yourls-advanced-analytics - URL: https://github.com/miconda/yourls-advanced-analytics
- Features: Detailed visit analytics, charts, geographic data
3. Password Protected URLs
- Plugin:
yourls-password-protection - URL: https://github.com/MatthewC/yourls-password-protection
- Features: Require password before redirecting
Usage:
# Create password-protected short URL via API
curl "http://go.yourdomain.com/yourls-api.php?signature=YOUR_SIGNATURE&action=shorturl&url=https://secret-content.com&keyword=secret&password=mypass123&format=json" 4. Link Expiry
- Plugin:
yourls-expiry - URL: https://github.com/joshp23/YOURLS-Expiry
- Features: Auto-expire links after date or click limit
5. API Action Plugins
- Plugin:
yourls-api-edit-url - URL: https://github.com/timcrockford/yourls-api-edit-url
- Features: Edit existing URLs via API
6. Preview URL
- Plugin:
yourls-preview-url - URL: https://github.com/YOURLS/YOURLS-preview-url
- Features: Show preview page before redirect (anti-phishing)
Usage: Access preview at https://go.yourdomain.com/abc12~
7. Google Analytics
- Plugin:
yourls-google-analytics - URL: https://github.com/powerthazan/YOURLS-Google-Analytics-Plugin
- Features: Integrate with Google Analytics for advanced tracking
8. Bulk Import
- Plugin:
yourls-import-export - URL: https://github.com/YOURLS/YOURLS-Import-Export
- Features: Bulk import from CSV, export database
9. Public API
- Plugin:
yourls-public-prefix-n-shorten - URL: https://github.com/YOURLS/public-prefix-n-shorten
- Features: Allow public shortening with prefix restrictions
10. Random Keywords
- Plugin:
yourls-random-keywords - URL: https://github.com/YOURLS/random-keywords
- Features: Generate pronounceable random keywords instead of alphanumeric
Bookmarklets
Bookmarklets enable one-click URL shortening from any webpage.
Setup Bookmarklets
- Navigate to:
http://go.yourdomain.com/admin/tools.php - Find “Bookmarklets” section
- Drag one of these bookmarklets to browser bookmark bar:
Standard Bookmarklet:
- Shortens current page URL
- Opens popup with short URL
Shorten and Copy:
- Shortens current page
- Copies short URL to clipboard
- No popup (silent operation)
Shorten and Tweet:
- Shortens current page
- Opens Twitter with pre-filled tweet containing short URL
Custom Bookmarklet
Create custom bookmarklet with auto-copy functionality:
javascript:(function(){var url='https://go.yourdomain.com/yourls-api.php?signature=YOUR_SIGNATURE&action=shorturl&format=json&url='+encodeURIComponent(location.href);fetch(url).then(r=>r.json()).then(d=>{navigator.clipboard.writeText(d.shorturl);alert('Short URL copied: '+d.shorturl)})})(); To use:
- Create new bookmark in browser
- Name: “Shorten & Copy”
- Paste JavaScript code as URL
- Save to bookmark bar
Usage: Click bookmarklet on any page to instantly shorten and copy URL.
Public vs. Private Mode
YOURLS can operate in public or private mode.
Private Mode (Default)
Only logged-in users can create short URLs.
Configuration: Already set by default with admin credentials.
Best for:
- Personal use
- Internal team links
- Controlled URL creation
Public Mode
Anyone can create short URLs (with optional restrictions).
Enable public mode:
Install “Public Prefix & Shorten” plugin:
cd ~/yourls/plugins
git clone https://github.com/YOURLS/public-prefix-n-shorten.git Activate in admin panel → Plugins.
Configure prefix restriction:
Edit plugin settings to require prefix for public URLs:
- Public URLs must start with specific prefix (e.g.,
pub-) - Prevents abuse while allowing public use
Example: Public users create pub-example, admins create example.
Rate Limiting
Protect public instances from abuse:
Install rate limiting plugin:
cd ~/yourls/plugins
git clone https://github.com/YOURLS/yourls-api-rate-limit.git Configuration:
- Limit: 10 URLs per hour per IP
- Customizable per plugin settings
Analytics and Tracking
Built-in Analytics
YOURLS includes basic analytics:
- Navigate to: “List URLs” in admin panel
- Click number in “Clicks” column for any URL
- View click details:
- Total clicks
- Click timeline
- Individual click timestamps
- Referrer information
Enhanced Analytics with Plugin
Install advanced analytics plugin:
cd ~/yourls/plugins
git clone https://github.com/miconda/yourls-advanced-analytics.git advanced-analytics Activate in admin panel.
Features:
- Geographic distribution maps
- Browser/OS breakdown
- Device type analysis
- Referrer statistics
- Time-based charts
- Export to CSV
Google Analytics Integration
For enterprise-grade analytics:
cd ~/yourls/plugins
git clone https://github.com/powerthazan/YOURLS-Google-Analytics-Plugin.git google-analytics Setup:
- Activate plugin in admin panel
- Navigate to plugin settings
- Enter Google Analytics tracking ID
- Configure tracking options
Result: Every short URL click tracked in Google Analytics with custom events.
Security Hardening
Restrict Admin Access
Method 1: Firewall rules
# Allow admin access only from local network
sudo ufw allow from 192.168.1.0/24 to any port 8080 Method 2: Nginx IP restriction
See reverse proxy configuration above for location-based IP restrictions.
Method 3: VPN-only access
Require Tailscale/WireGuard VPN for admin panel access:
# Only allow admin access via Tailscale IPs
location /admin/ {
allow 100.64.0.0/10; # Tailscale CGNAT range
deny all;
proxy_pass http://localhost:8080;
} Enable HTTPS Only
Force HTTPS redirects in reverse proxy (see Nginx/Caddy configs above).
Update YOURLS configuration:
environment:
YOURLS_SITE: https://go.yourdomain.com Change Default Admin Path
Obfuscate admin panel location:
# Copy admin files to custom location
docker exec -it yourls bash
cp -r /var/www/html/admin /var/www/html/secret-admin-path Access admin at: https://go.yourdomain.com/secret-admin-path/
Regular Password Updates
# Generate new strong password
openssl rand -base64 20
# Update docker-compose.yml
# Restart container
docker compose restart yourls Troubleshooting
Issue 1: Cannot Access Admin Panel
Symptoms: 404 error on /admin/ path.
Solutions:
- Verify container is running:
docker ps | grep yourls - Check logs:
docker logs yourls - Ensure reverse proxy forwards
/admin/path correctly - Test direct access:
curl -I http://localhost:8080/admin/
Issue 2: Database Connection Errors
Symptoms: “Error connecting to database” message.
Diagnosis:
# Check database container
docker ps | grep yourls-db
# View database logs
docker logs yourls-db
# Test connection from YOURLS container
docker exec -it yourls mysql -h mysql -u yourls -p Solutions:
- Verify database password matches in both containers
- Ensure database has fully initialized (wait 30 seconds after first start)
- Check network connectivity:
docker network inspect yourls-net
Issue 3: Short URLs Not Redirecting
Symptoms: Short URL shows YOURLS error page instead of redirecting.
Solutions:
- Check URL exists: View “List URLs” in admin panel
- Verify keyword spelling (case-sensitive)
- Check for expired/deactivated plugins
- Review YOURLS error logs:
docker logs yourls | grep -i error
Issue 4: Plugins Not Activating
Symptoms: Plugin activation fails or shows error.
Solutions:
- Verify plugin files in correct directory:
ls -la ~/yourls/plugins/ - Check file permissions:
chmod -R 755 ~/yourls/plugins/ - Review plugin requirements (some require PHP extensions)
- Check container logs during activation:
docker logs -f yourls
Issue 5: API Returns Invalid Signature
Symptoms: API calls fail with “Invalid signature” error.
Solutions:
- Verify signature from:
http://go.yourdomain.com/admin/tools.php - Check signature hasn’t changed (regenerates if cookiekey changes)
- Ensure no extra spaces in signature parameter
- Test with username/password instead:
&username=admin&password=yourpass
Backup and Maintenance
Automated Backup Script
#!/bin/bash
# backup-yourls.sh
BACKUP_DIR="/backups/yourls"
DATE=$(date +%Y%m%d-%H%M%S)
# Create backup directory
mkdir -p "$BACKUP_DIR"
# Backup MySQL database
docker exec yourls-db mysqldump -u yourls -psecure_password_here yourls | gzip > "$BACKUP_DIR/yourls-db-$DATE.sql.gz"
# Backup plugins and custom pages
tar czf "$BACKUP_DIR/yourls-plugins-$DATE.tar.gz" -C ~/yourls plugins pages
# Backup configuration
cp ~/yourls/docker-compose.yml "$BACKUP_DIR/docker-compose-$DATE.yml"
# Remove backups older than 30 days
find "$BACKUP_DIR" -name "yourls-db-*.sql.gz" -mtime +30 -delete
find "$BACKUP_DIR" -name "yourls-plugins-*.tar.gz" -mtime +30 -delete
echo "Backup completed: $DATE" Make executable and schedule:
chmod +x backup-yourls.sh
# Add to crontab (daily at 2 AM)
crontab -e
0 2 * * * /root/backup-yourls.sh >> /var/log/yourls-backup.log 2>&1 Restore from Backup
#!/bin/bash
# restore-yourls.sh
BACKUP_FILE="$1" # Path to .sql.gz backup file
if [ -z "$BACKUP_FILE" ]; then
echo "Usage: $0 /path/to/backup.sql.gz"
exit 1
fi
# Stop YOURLS container
docker compose stop yourls
# Restore database
zcat "$BACKUP_FILE" | docker exec -i yourls-db mysql -u yourls -psecure_password_here yourls
# Restart containers
docker compose start yourls
echo "Restore completed from: $BACKUP_FILE" Update YOURLS
cd ~/yourls
# Backup before updating
./backup-yourls.sh
# Pull latest image
docker compose pull
# Restart with new image
docker compose up -d
# Check version
docker logs yourls | head -20 Database Maintenance
# Optimize database (quarterly)
docker exec -it yourls-db mysql -u yourls -psecure_password_here yourls -e "OPTIMIZE TABLE yourls_url, yourls_options, yourls_log;"
# Check database size
docker exec -it yourls-db mysql -u yourls -psecure_password_here yourls -e "SELECT table_name AS 'Table', ROUND(((data_length + index_length) / 1024 / 1024), 2) AS 'Size (MB)' FROM information_schema.TABLES WHERE table_schema = 'yourls';" Migration and Import
Import from Bitly
Export Bitly links and import to YOURLS:
- Export from Bitly (CSV format)
- Install import plugin:
cd ~/yourls/plugins git clone https://github.com/YOURLS/YOURLS-Import-Export.git import-export - Activate plugin in admin panel
- Navigate to: Tools → Import
- Upload CSV file
- Map columns appropriately
- Click “Import”
Import from Other Services
Most URL shorteners support CSV export. Format CSV:
keyword,url,title,timestamp
example1,https://example.com/page1,Example Page 1,2025-01-15 10:30:00
example2,https://example.com/page2,Example Page 2,2025-01-15 10:31:00 Use import plugin to bulk upload.
Advanced Customization
Custom Homepage
Create custom landing page at root URL:
# Create custom index page
cat > ~/yourls/pages/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>My URL Shortener</title>
<style>
body {
font-family: Arial, sans-serif;
max-width: 600px;
margin: 100px auto;
text-align: center;
}
h1 { color: #333; }
.shortener {
margin-top: 40px;
}
input[type="text"] {
width: 70%;
padding: 10px;
font-size: 16px;
}
button {
padding: 10px 20px;
font-size: 16px;
background: #007bff;
color: white;
border: none;
cursor: pointer;
}
</style>
</head>
<body>
<h1>URL Shortener</h1>
<p>Shorten your long URLs quickly</p>
<div class="shortener">
<input type="text" id="longUrl" placeholder="Enter long URL here">
<button onclick="shortenUrl()">Shorten</button>
<p id="result"></p>
</div>
<script>
function shortenUrl() {
const longUrl = document.getElementById('longUrl').value;
const apiUrl = '/yourls-api.php?signature=YOUR_SIGNATURE&action=shorturl&format=json&url=' + encodeURIComponent(longUrl);
fetch(apiUrl)
.then(r => r.json())
.then(d => {
document.getElementById('result').innerHTML =
'<strong>Short URL:</strong> <a href="' + d.shorturl + '">' + d.shorturl + '</a>';
});
}
</script>
</body>
</html>
EOF Update docker-compose.yml to map custom homepage:
volumes:
- ./pages/index.html:/var/www/html/index.html Custom Error Pages
Create custom 404 page:
cat > ~/yourls/pages/404.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>404 - Short URL Not Found</title>
<style>
body { font-family: Arial; text-align: center; margin-top: 100px; }
h1 { color: #d9534f; }
</style>
</head>
<body>
<h1>404 - Short URL Not Found</h1>
<p>The short URL you requested does not exist.</p>
<p><a href="/">Return to homepage</a></p>
</body>
</html>
EOF Map in docker-compose.yml:
volumes:
- ./pages/404.html:/var/www/html/404.html Conclusion
You now have a fully functional YOURLS URL shortener with:
- Custom branded short domain
- Admin interface for URL management
- REST API for automation
- Plugin ecosystem for extended functionality
- Bookmarklets for one-click shortening
- Analytics and tracking capabilities
- Secure, self-hosted infrastructure
Next steps:
- Install essential plugins (QR codes, analytics, password protection)
- Set up bookmarklets for daily use
- Configure API for application integrations
- Customize homepage and branding
- Implement automated backups
- Explore plugin ecosystem for additional features
YOURLS proves that sometimes the classics are classics for a reason. With 15+ years of development, extensive plugin support, and rock-solid reliability, YOURLS remains the gold standard for self-hosted URL shortening. Whether you’re managing personal links or running a full-scale URL shortening service, YOURLS provides the flexibility and control you need.
Additional Resources
Official:
Plugins:
Community:
Tools:
Last Updated: January 2025 Version Covered: YOURLS 1.9.2+