Free DynDNS

Documentation

Everything needed to point a router or a script at bhdns.de: the update protocol, settings for AVM FRITZ!Box and Telekom Speedport, ready-made scripts, IPv6 handling and the limits of the free tier.

Documentation

Quick start

Claim a subdomain, then point your router or a script at the update URL. The record updates within a second; the TTL is 60 seconds, and both IPv4 (A) and IPv6 (AAAA) are supported.

You can choose the domain in the form — bhdns.de or sbdns.de. The name you pick is created as <label>.<domain>, the same label may exist in both domains, and the free limits are shared across them. Address detection always runs through v4.bhdns.de / v6.bhdns.de: those names only tell your browser which address it is using, so they are independent of the domain you pick.

  1. Create an account and confirm the 6-digit code — sign up.
  2. Add a subdomain such as my-home.
  3. Copy the update token from the subdomain dialog — it is shown once.
  4. Enter URL, domain, username and token into your router (below) or run a script.

Values your client needs

Update addressupdate.bhdns.de/nic/update — one address for every client. Routers that ask for the address, the protocol and the port separately take it bare, exactly as written; a script or an app that takes a whole URL writes https://update.bhdns.de/nic/update. It is not the bare domain on purpose: a router that resolved bhdns.de before the domain was delegated may still hold the registrar's old 127.0.0.1 in its cache and send the update to itself, while nothing can be cached for a name that did not exist yet.
Domain / hostnamemy-home.bhdns.de
Usernamemy-home.bhdns.de (the same full hostname)
Passwordyour update token, e.g. bhdns_9f2c… — 30 characters, short enough for the FRITZ!Box field (32) and the Speedport (50)

Protocol and port are not optional. The service answers on HTTPS, port 443. Plain HTTP is only redirected to HTTPS and routers do not follow that redirect, so an http:// URL or the wrong port fails with an error the router shows as "not registered".

DynDNS2

Update protocol

The endpoint follows the dyndns2 convention that routers and clients already speak, with HTTP Basic authentication. GET and POST both work.

GET https://update.bhdns.de/nic/update?hostname=my-home.bhdns.de&myip=203.0.113.47&myipv6=2a01:4f8::1
Authorization: Basic base64("my-home.bhdns.de:<token>")
ParameterMeaning
hostnameFull hostname. Several names may be comma-separated.
myipIPv4 address → written as an A record. May be a comma-separated list: every address goes to the record of its own family, so an IPv6 address here also works (the Speedport Smart 4 sends myip=<ipv6>,<ipv4>).
myipv6IPv6 address → written as an AAAA record.

Send both parameters to keep both records current. If neither is sent, the address of the request itself is used. Only the changed family is rewritten — the other record stays untouched.

Answers

AnswerMeaning
good <ip>The record was updated.
nochg <ip>The address is already current; nothing was written.
badauthWrong token, or none sent.
nohostThe hostname does not exist on this service.
notfqdnNo hostname was given.
abuseA limit was hit — see Limits.
911The address was unreadable (for example text in myip).
Address families

IPv6 and AAAA records

Routers such as the FRITZ!Box and the Speedport send IPv4 and IPv6 in the same update, so a subdomain normally gets both an A and an AAAA record. If you do not want the IPv6 address published — for example because your provider rotates the prefix and some clients then fail — open the subdomain in the dashboard and choose Remove IPv6.

That is a setting for this subdomain, not a one-off deletion: from then on the server ignores the IPv6 address your router sends, so the AAAA record does not come back with the next update. Choose Allow IPv6 to undo it — the record returns with the next update from your router.

Every subdomain keeps at least one address. If it has no IPv4 address yet, IPv6 cannot be switched off: add an IPv4 address first, otherwise the name would stop resolving entirely.

AVM

AVM FRITZ!Box

FRITZ!OS has a built-in DynDNS client that also sends IPv6. Menu names differ a little between versions; the field values do not.

  1. Open Internet → Shares → DynDNS (on some versions Internet → Permit Access → DynDNS).
  2. Tick Use dynamic DNS.
  3. Dynamic DNS provider: User-defined.
  4. Update URL — enter exactly this, including the placeholders:
    https://update.bhdns.de/nic/update?hostname=<domain>&myip=<ipaddr>&myipv6=<ip6addr>
  5. Domain name: my-home.bhdns.de
  6. Username: my-home.bhdns.de
  7. Password: your update token.

FRITZ!Box replaces <domain>, <ipaddr> and <ip6addr> itself, so both records stay current. If your firmware rejects the URL, remove the two address parameters and let the router send only hostname — the service then uses the address the request came from.

The FRITZ!Box has a single Update URL field, so here the scheme does belong in the URL. This is the opposite of routers whose form separates the address from the protocol and the port (see Speedport and other routers), where https:// in the address field is rejected.

Telekom

Telekom Speedport

Speedport models expose dynamic DNS under Internet → Dynamic DNS (naming varies by model and firmware). The form splits the destination into an address, a protocol and a port — and it rejects the address if you paste https:// into it. Enter the address bare and choose the protocol and the port in their own fields.

Provider / AnbieterUser-defined / Other / Anderer Anbieter
Name (labelled Hostname on some firmwares)my-home.bhdns.de — the whole name, not just my-home
Username / Benutzermy-home.bhdns.de — the same whole name
Passwortyour update token
Updateserver-Adresseupdate.bhdns.de/nic/update — no https://, no port, no trailing slash
ProtokollHTTPS — mandatory. Plain HTTP is only redirected, and the Speedport does not follow redirects.
Port443 — mandatory. Encrypted HTTPS port; anything else times out.

You do not have to guess which field carries the name. Whichever field the firmware sends it in — the query string, Name or Username — the update works. If none of them contains the whole name, the server still recognises the subdomain from the token alone, because a token belongs to exactly one subdomain. Enter the same full name in Name and Username and it works on every firmware.

The status field may keep saying not registered until the first successful update has gone through — it is the router's own display, not our answer. If it stays that way, check the router's log: a valid request is answered with good <ip> or nochg <ip>, and badauth means the token is wrong.

Many Speedport versions do not offer IPv6 for dynamic DNS. In that case the A record is maintained by the router, and IPv6 can be updated by a script (below) or by ticking IPv6 in a newer firmware.

More

Other routers and NAS

Anything that speaks dyndns2 works — choose "user-defined" provider and use the values from the quick start.

Address, protocol and port are three separate fields on most routers. Into the address field goes update.bhdns.de/nic/update — bare, without https://, without a port and without a trailing slash. Then select HTTPS and port 443; the service answers on nothing else. A router that shows "not registered" while its log says the URL was refused has almost always had the scheme pasted into the address field.

  • OpenWrt: opkg install ddns-scripts luci-app-ddns, then Services → Dynamic DNS → provider custom, update URL https://update.bhdns.de/nic/update?hostname=[DOMAIN]&myip=[IP]&myipv6=[IP6], domain, username and token.
  • Synology DSM: Control Panel → External Access → DDNS → Add → Service provider Customize, with the same URL and credentials.
  • pfSense / OPNsense: Services → Dynamic DNS → Add, Service type Custom, interface (IPv4 and/or IPv6), URL with %IP%/%IP6% placeholders.
  • Raspberry Pi, servers, containers: use the scripts below with a cron job or a systemd timer.
Scripts

Scripts you can copy

Each script sends both addresses when it can read them. Replace the three values at the top with your own.

Linux / macOS (bash)

#!/bin/sh
HOST="my-home.bhdns.de"
TOKEN="bhdns_your_token"
URL="https://update.bhdns.de/nic/update"

IP4=$(curl -4 -fsS https://bhdns.de/nic/whoami || true)
IP6=$(curl -6 -fsS https://bhdns.de/nic/whoami || true)

curl -fsS -u "$HOST:$TOKEN" \
  "$URL?hostname=$HOST&myip=$IP4&myipv6=$IP6"
echo

Cron (every five minutes)

*/5 * * * * /usr/local/bin/bhdns-update.sh >/dev/null 2>&1

systemd timer (better than cron)

# /etc/systemd/system/bhdns-update.service
[Unit]
Description=Update bhdns.de dynamic DNS

[Service]
Type=oneshot
ExecStart=/usr/local/bin/bhdns-update.sh

# /etc/systemd/system/bhdns-update.timer
[Unit]
Description=Run bhdns.de update every 5 minutes

[Timer]
OnBootSec=2min
OnUnitActiveSec=5min

[Install]
WantedBy=timers.target

Then: systemctl enable --now bhdns-update.timer.

Windows (PowerShell)

$host_ = "my-home.bhdns.de"
$token = "bhdns_your_token"
$pair  = $host_ + ":" + $token
$auth  = [Convert]::ToBase64String([Text.Encoding]::ASCII.GetBytes($pair))

# IPv4 (required), IPv6 if your network supports it
$ip4 = (Invoke-RestMethod "https://bhdns.de/nic/whoami")
$ip6 = ""
try { $ip6 = (Invoke-RestMethod "https://bhdns.de/nic/whoami" -LocalAddress "::") } catch {}

$url = "https://update.bhdns.de/nic/update?hostname=$host_&myip=$ip4&myipv6=$ip6"
Invoke-RestMethod $url -Headers @{ Authorization = "Basic $auth" }

Docker / NAS one-liner

curl -fsS -u "my-home.bhdns.de:bhdns_your_token" \
  "https://update.bhdns.de/nic/update?hostname=my-home.bhdns.de"

Without myip the service uses the address the request came from, which is what you want for a one-liner.

Fair use

Limits of the free tier

We host subdomains under two domains: bhdns.de and sbdns.de — you pick one when you claim a name, and the limits are shared across both (three subdomains in total). Bringing your own domain is not supported yet. The free tier has the same shape as the Standard plan at ipv64.net: three subdomains and 64 updates in 24 hours.

The 64 are counted as address changes, not as requests. A router may ask as often as it likes — that is how FRITZ!Box works — but the address may only be rewritten this many times:

LimitValue
Subdomains per account5
Address changes per host / 24 h50
Requests per host / 24 h2000
Requests per address / 24 h3000
Shortest gap between two changes30 s
New subdomains per account / 24 h10

A two-letter name is reserved for a paid tier; free names have at least three characters. When a limit is hit the client receives abuse, and the reason is written to the log.

Names are also refused when they contain words used for abuse, piracy or adult material — including simple disguises such as p-o-r-n or p0rn. This applies to every account.

Abuse

Abuse reports

If a subdomain is reported for abuse — spam, phishing, malware or anything else illegal — that single name is suspended. It stops answering DNS immediately and you cannot activate it yourself; only an administrator can lift the suspension. The rest of your account keeps working.

A suspension is not a verdict: if the report was wrong, get in touch (see the imprint for the address) and it will be reviewed and lifted. Suspensions are never deleted automatically, and every one is recorded with the report it is based on.

You can always delete the subdomain yourself, suspension or not — that removes the name from DNS at once and frees it.

To report a subdomain used for phishing, malware or spam, use the abuse form. Every report is recorded, an administrator is notified and the subdomain can be suspended immediately.

We do not send e-mail about suspensions, bans or administrator actions. Every such change appears in the notification centre — the bell in the header of every page. If your account is suspended you cannot sign in, so the sign-in page tells you what happened and where to get in touch; the notice is waiting in the centre as soon as the suspension is lifted.

Questions

Questions

How fast does a change appear?

Immediately on this server. The secondary nameserver picks it up on the next transfer, and resolvers may cache the old answer until the 60-second TTL expires.

Why was my e-mail refused?

Disposable inbox services (10minutemail, mailinator, yopmail and similar) are not accepted: the address disappears within minutes, so the account could never be recovered. Use an address you actually keep.

I lost my token

Open the subdomain in your dashboard and issue a new one. The old token stops working at that moment, so update the router afterwards.

My router refuses the password

Some routers limit how long the password field may be — the FRITZ!Box accepts 32 characters, the Speedport Smart 4 no more than 50. Tokens issued by this service are 30 characters, so they fit. If you still have an older, longer token from before that change, issue a new one in the dashboard.

My address is behind NAT

The service stores whatever address you send. Behind carrier-grade NAT that is the provider address — reachability then depends on your provider, not on DNS.

Can I point the name at a private address?

Yes. The service does not filter addresses; a private address is useful for VPN and LAN setups. It will not be reachable from the internet, of course.

Is there an API for my own tooling?

The update protocol is the API: one GET with Basic auth. Any client that speaks dyndns2 works unchanged.

Something unclear or a router that refuses to work? The logs in your dashboard show every attempt with its answer, which is the fastest way to see what the router sent.