Docs / Developer tools

Developer utilities API

Cron in words, UUIDs and ULIDs, hashes and HMACs, JWT decoding, user agents and time zones.

Small tools a program or an assistant needs often. Times are in India time unless you name a zone.

Base URL https://api.dharun.devNo key needed for most600 units a minute, 3000 with a free keyThis page as Markdown

Explain a cron expression

GET/v1/cron

The expression in words and its next run times.

ParameterDescription
exprquery, requiredFive fields, or @daily, @hourly, @weekly, @monthly, @yearly.
tzqueryTime zone the schedule runs in. Default Asia/Kolkata.
countqueryNext runs, 1 to 50. Default 5.
fromqueryStart from this time instead of now.

curl

curl "https://api.dharun.dev/v1/cron?expr=30%209%20*%20*%201-5&utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/cron?expr=30%209%20*%20*%201-5&utm_medium=docs");
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.get("https://api.dharun.dev/v1/cron?expr=30%209%20*%20*%201-5&utm_medium=docs", timeout=10)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

New UUIDs, ULIDs and nano ids

GET/v1/uuid

ParameterDescription
kindqueryDefault uuid4. One of: uuid4, uuid7, ulid, nanoid.
countquery1 to 100. Default 1.

curl

curl "https://api.dharun.dev/v1/uuid?kind=uuid7&count=3&utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/uuid?kind=uuid7&count=3&utm_medium=docs");
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.get("https://api.dharun.dev/v1/uuid?kind=uuid7&count=3&utm_medium=docs", timeout=10)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Read a UUID or ULID

GET/v1/uuid/{id}

Its version and variant, and the time inside a version 1 or 7 UUID or a ULID.

ParameterDescription
idpath, requiredThe UUID or ULID.

curl

curl "https://api.dharun.dev/v1/uuid/01936f4e-5a6a-7cc2-9a4b-3e5b2a1f0c11?utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/uuid/01936f4e-5a6a-7cc2-9a4b-3e5b2a1f0c11?utm_medium=docs");
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.get("https://api.dharun.dev/v1/uuid/01936f4e-5a6a-7cc2-9a4b-3e5b2a1f0c11?utm_medium=docs", timeout=10)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Response

{
  "data": {
    "kind": "uuid",
    "version": 7,
    "variant": "RFC 9562",
    "time": "2024-11-27T20:27:06.218Z"
  },
  "meta": {}
}

Hashes and HMACs

GET/v1/hashPOST

MD5, SHA-1, SHA-2, SHA-3, BLAKE2b and CRC-32 of a text, in hex and base64; with key, HMACs.

Also takes POST: The text, as text/plain, or JSON {"text": "...", "algo": "sha256", "key": "..."}. Send it as text/plain, or as JSON {"text": "..."} with the other options beside it, up to 256 KB.

What you send here is never written to the log, and the answer is not cached.

ParameterDescription
textqueryThe text.
algoqueryComma-separated: md5, sha1, sha256, sha384, sha512, sha3-256, sha3-512, blake2b-256, crc32. Default md5,sha1,sha256,sha512.
keyqueryFor an HMAC. Send it in a POST body.

curl

curl "https://api.dharun.dev/v1/hash?text=hello&algo=sha256,md5&utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/hash?text=hello&algo=sha256,md5&utm_medium=docs");
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.get("https://api.dharun.dev/v1/hash?text=hello&algo=sha256,md5&utm_medium=docs", timeout=10)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Response

{
  "data": {
    "md5": {
      "hex": "5d41402abc4b2a76b9719d911017c592",
      "base64": "XUFAKrxLKna5cZ2REBfFkg=="
    },
    "sha256": {
      "hex": "2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
      "base64": "LPJNul+wow4m6DsqxbninhsWHlwfp0JecwQzYpOLmCQ="
    }
  },
  "meta": {
    "note": "Digests of the text's UTF-8 bytes."
  }
}

Decode a JWT

GET/v1/jwt/decodePOST

The header, payload and times of a JSON Web Token. The signature is not checked.

Also takes POST: The token, as text/plain or JSON {"text": "..."}. Send it as text/plain, or as JSON {"text": "..."} with the other options beside it, up to 256 KB.

What you send here is never written to the log, and the answer is not cached.

ParameterDescription
textqueryThe token.

curl

curl "https://api.dharun.dev/v1/jwt/decode?text=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkZW1vIiwiaWF0IjoxNzYyODQ4MDAwfQ.c2ln&utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/jwt/decode?text=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkZW1vIiwiaWF0IjoxNzYyODQ4MDAwfQ.c2ln&utm_medium=docs");
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.get("https://api.dharun.dev/v1/jwt/decode?text=eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJkZW1vIiwiaWF0IjoxNzYyODQ4MDAwfQ.c2ln&utm_medium=docs", timeout=10)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Response

{
  "data": {
    "header": {
      "alg": "HS256"
    },
    "payload": {
      "iat": 1762848000,
      "sub": "demo"
    },
    "signature": "c2ln",
    "times": {
      "iat": "2025-11-11T08:00:00Z"
    },
    "warnings": []
  },
  "meta": {
    "note": "Decoded only: the signature is NOT checked, so nothing here proves who made the token. Never paste a live token you do not own."
  }
}

Read a user agent

GET/v1/user-agent

Browser, engine, system, device and vendor, and whether it is a person, an AI assistant, a crawler or a program. Without ua, your own request's.

ParameterDescription
uaqueryA User-Agent header. Default: yours.

curl

curl "https://api.dharun.dev/v1/user-agent?ua=Mozilla%2F5.0%20(Linux%3B%20Android%2014%3B%20SM-S918B)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F131.0.0.0%20Mobile%20Safari%2F537.36&utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/user-agent?ua=Mozilla%2F5.0%20(Linux%3B%20Android%2014%3B%20SM-S918B)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F131.0.0.0%20Mobile%20Safari%2F537.36&utm_medium=docs");
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.get("https://api.dharun.dev/v1/user-agent?ua=Mozilla%2F5.0%20(Linux%3B%20Android%2014%3B%20SM-S918B)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F131.0.0.0%20Mobile%20Safari%2F537.36&utm_medium=docs", timeout=10)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Convert a time between zones

GET/v1/time

"3 pm IST in Berlin": a time read many ways (2026-11-11 15:00, 3pm, a Unix time) in one zone, shown in others with their offsets and the day difference.

ParameterDescription
atqueryThe time. Default now.
fromqueryIts zone: IANA name, short name, city or offset. Default India.
toqueryZones to show it in, separated by commas. Default UTC.

curl

curl "https://api.dharun.dev/v1/time?at=2026-11-11%2015%3A00&from=IST&to=Europe%2FBerlin,PST,SGT&utm_medium=docs"

JavaScript

const response = await fetch("https://api.dharun.dev/v1/time?at=2026-11-11%2015%3A00&from=IST&to=Europe%2FBerlin,PST,SGT&utm_medium=docs");
const body = await response.json();
if (!response.ok) throw new Error(body.error.message);
console.log(body.data);

Python

import requests

response = requests.get("https://api.dharun.dev/v1/time?at=2026-11-11%2015%3A00&from=IST&to=Europe%2FBerlin,PST,SGT&utm_medium=docs", timeout=10)
body = response.json()
if not response.ok:
    raise RuntimeError(body["error"]["message"])
print(body["data"])
Try it here

Change the values and send the request from your browser. Needs JavaScript.

Using an AI assistant? Connect the MCP server and it can call this API by itself. Want every endpoint on one bench? Open the playground.