Blog

  • JWT Decoder Online: Inspect Tokens in Browser [2026]

    JWT Decoder Online: Inspect Tokens in Browser [2026]

    TL;DR: A JWT decoder splits a JSON Web Token into its three Base64-URL-encoded parts — header, payload, signature — and renders them as readable JSON. Use it to inspect what an API token actually claims (user ID, expiry, scopes), debug auth issues, or build new tokens. Our free JWT encoder/decoder handles HS256 and RS256, verifies signatures locally, and never transmits the token.

    JWT (JSON Web Token) is the auth standard for modern APIs. Every OAuth flow, every Auth0 / Cognito / Firebase Auth integration, every internal microservice that needs to pass identity around — all of them use JWTs. The token looks like gibberish: eyJhbGciOi…. Decoded, it’s three small JSON objects that say “this user, signed by this issuer, valid until this time”. Decoding is non-secret — anyone with the token can read its contents. Verifying the signature requires the secret. Both operations are routine for backend developers and frequently need a quick lookup tool.

    Our JWT encoder/decoder takes any JWT string and renders the header + payload as pretty-printed JSON. Optionally paste the secret to verify the signature, or build a fresh token from custom JSON. Everything runs in your browser via the Web Crypto API; the token and secret never transmit. This guide explains JWT structure, the differences between HS256 and RS256, and the security gotchas that have produced real-world authentication failures.

    JWT structure — three Base64-URL parts joined by dots

    eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkphbmUiLCJpYXQiOjE2NjcwMDAwMDB9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
       ↑ header                ↑ payload                                                        ↑ signature
       {"alg":"HS256"}          {"sub":"1234567890","name":"Jane","iat":1667000000}
    • Header: the algorithm used (HS256, RS256, etc.) and the token type. Always JSON.
    • Payload: the claims — user ID, scopes, issued-at, expiry, custom application data. The actual identity assertion.
    • Signature: a cryptographic signature of header.payload using either a shared secret (HS256) or the issuer’s private key (RS256). This is what makes the token tamper-evident.

    Standard claims every JWT might include

    Claim Meaning
    sub Subject — usually the user ID
    iss Issuer — who created the token
    aud Audience — who the token is for
    exp Expiry — Unix timestamp after which the token is invalid
    iat Issued-at — Unix timestamp of token creation
    nbf Not-before — token isn’t valid until this time
    jti JWT ID — unique identifier for revocation lists

    Beyond the standard claims, applications add custom claims (scopes, roles, email, anything else). Decoding a token reveals all claims; this is why JWTs should never carry secrets.

    HS256 vs RS256 — choosing the right algorithm

    • HS256 (HMAC-SHA-256): uses a shared secret known to both signer and verifier. Simpler, faster, smaller signatures. Right when one service signs and the same service verifies. Wrong when verification needs to happen on multiple machines without sharing a secret.
    • RS256 (RSA + SHA-256): uses asymmetric crypto. Issuer holds a private key; verifiers use the public key. Right for any “sign here, verify everywhere” pattern (Auth0, Firebase Auth, Google OAuth all use RS256). The public key can be distributed freely.
    • ES256 (ECDSA): elliptic-curve variant of RS256. Smaller signatures, faster signing, equivalent security. Increasingly common in IoT and mobile contexts.

    The rule of thumb: HS256 for monolithic apps where one service signs and verifies. RS256 for anything multi-service, distributed, or where third parties need to verify.

    How to use the browser JWT decoder

    1. Open the JWT encoder/decoder
    2. Paste your JWT into the input. Header and payload appear as pretty-printed JSON instantly
    3. Optional: paste the signing secret (HS256) or public key (RS256) to verify the signature. Result shows ✓ valid or ✗ invalid
    4. Switch to Encode mode to build a new token from custom JSON
    5. Copy any decoded part with the per-section copy buttons

    Real-world JWT security mistakes

    • The “alg: none” attack. Some libraries trust the algorithm specified in the header. Setting it to “none” tells the library to skip signature verification. Always specify the expected algorithm at verification time.
    • Confusing HS256 with RS256. If a service expects RS256 but accepts HS256 with the public key as the secret, attackers can forge tokens. Always pin the algorithm.
    • Leaving secrets in JWT payloads. JWTs are encoded, not encrypted. Anyone with the token reads the payload. Never put passwords, API keys, or PII in claims.
    • Long expiry times. A 90-day JWT can’t be revoked without maintaining a denylist. Keep exp short (15-60 minutes) and use refresh tokens for sustained sessions.
    • Using HS256 with weak secrets. A 16-byte secret is brute-forceable. Use 32+ bytes (256 bits) of randomness for HS256 secrets.

    Decoding JWT in code

    // Node.js (jsonwebtoken — most common)
    import jwt from "jsonwebtoken";
    
    const decoded = jwt.decode(token);                 // unverified
    const verified = jwt.verify(token, secret);         // throws if invalid
    
    // Browser (jose — modern, no deps)
    import * as jose from "jose";
    
    const decoded = jose.decodeJwt(token);
    const { payload } = await jose.jwtVerify(token, await jose.importJWK(jwk));
    
    // Python (PyJWT)
    import jwt
    decoded = jwt.decode(token, secret, algorithms=["HS256"])
    
    // Manual decode (browser, no library)
    const [header, payload] = token.split(".").slice(0, 2)
      .map(seg => JSON.parse(atob(seg.replace(/-/g, "+").replace(/_/g, "/"))));

    When NOT to use JWT

    • For session storage. Sessions you need to revoke instantly are better as opaque session IDs in a database. JWT revocation requires a denylist that defeats the stateless benefit.
    • For sensitive payload data. Anyone with the token reads the claims. Store sensitive data server-side and reference by ID in the JWT instead.
    • For very long expiry. If your tokens last weeks, you’ve reinvented session storage with extra steps. Use refresh tokens with short-lived JWTs.
    • When you need cookie-based CSRF protection. JWTs in localStorage are vulnerable to XSS; in cookies they’re vulnerable to CSRF. Each pattern has trade-offs to design around.

    Frequently asked questions

    Is JWT encrypted?

    Standard JWT (JWS) is signed but not encrypted — anyone with the token can decode and read the payload. JWE (JSON Web Encryption) is the encrypted variant, much less common. Don’t put secrets in JWT claims.

    Can I decode a JWT without the secret?

    Yes. The header and payload are Base64-URL encoded — anyone can decode them. The secret is only needed to verify the signature (prove the token wasn’t forged) or to create a new token. Decoding without verification is fine for inspection but never trust an unverified JWT in production.

    How long should a JWT expire?

    15-60 minutes for access tokens. Pair with a refresh token (longer expiry, revocable, server-side stored) for sustained sessions. Short access-token expiry limits damage if a token is leaked.

    Is my JWT sent to your server when I decode it?

    No. Decoding happens entirely in your browser via the Web Crypto API and JavaScript Base64 decoding. The token, secret (if you paste one), and decoded output all stay on your device. Verify in DevTools Network tab — no requests during decoding.

    What’s the difference between HS256 and RS256?

    HS256 uses a shared secret known to signer and verifier (symmetric). RS256 uses an RSA key pair where the issuer holds the private key and verifiers use the public key (asymmetric). Use HS256 for one-service contexts, RS256 for distributed/multi-service auth.

    Can I edit a JWT and re-sign it?

    Yes — switch to Encode mode, edit the header or payload JSON, paste the secret, click Sign. The output is a new valid JWT. Useful for testing token-validation logic with custom payloads.

    Related tools and guides

     

  • URL Slug Generator: SEO-Friendly URLs in Seconds [2026]

    URL Slug Generator: SEO-Friendly URLs in Seconds [2026]

    TL;DR: A URL slug generator turns a page title into a clean, lowercase, hyphen-separated URL segment safe for SEO and shareability. “How to Cook Pasta!” becomes “how-to-cook-pasta”. Our free URL slug generator handles Unicode (transliterates accented characters), strips punctuation, collapses whitespace, and limits to 50-60 characters — the sweet spot for SEO.

    The URL slug is the part of a URL after the domain — example.com/this-is-the-slug/. Done well, slugs are shareable, SEO-friendly, and human-readable. Done badly (?p=12345&s=abc), they’re invisible to search engines and confusing to users. Every CMS auto-generates a slug from the post title, but the auto-generated version is often wrong: too long, retains stop words, includes special characters that need URL-encoding.

    Our URL slug generator takes any title and produces a clean slug — lowercase, hyphen-separated, transliterated for non-ASCII characters, with optional length cap. Built for content workflows where you publish multiple times a week and want consistent slugs. This guide explains what makes a good slug, the SEO implications of slug choices, and the gotchas with Unicode languages.

    What makes a good URL slug

    • Lowercase only. URLs are case-sensitive on most servers; mixed-case slugs cause 404s when shared with wrong casing.
    • Hyphens, not underscores. Google treats hyphens as word separators. Underscores are treated as word joiners (my_great_post reads as one token to crawlers).
    • Short — 50-60 characters maximum. Google truncates URLs in SERP after ~75 chars; long slugs look spammy and don’t fit in mobile snippets.
    • Stop words removed. “The”, “a”, “an”, “of”, “is” rarely add meaning to a slug. how-to-cook-pasta beats how-to-cook-the-best-pasta-of-your-life.
    • Keyword-front-loaded. Put the primary keyword first. nyc-best-pizza reads better than guide-to-the-best-pizza-in-nyc.
    • No punctuation, no spaces, no Unicode. Apostrophes, exclamation marks, accents, emojis — strip them all. They survive in modern browsers but break older ones, email links, and pasted URLs.

    How URL slugs affect SEO

    Slugs are a relatively minor ranking factor — Google has said as much in public communications — but they affect three signals that compound over time:

    • Click-through rate. Users see slugs in search results. example.com/best-running-shoes-2026 reads more relevant than example.com/post?id=12345. Clearer slugs win clicks.
    • Backlink anchor text. When other sites link to you, many use the URL itself as the anchor. A keyword-rich slug becomes free anchor text.
    • Social share previews. Twitter, Slack, and LinkedIn show URLs prominently. Clean slugs look more professional in shares.

    How to use the browser slug generator

    1. Open the URL slug generator
    2. Paste your post title or any text into the input
    3. The slug appears live as you type
    4. Toggle “Strip stop words” (the/a/an/of/etc. removed)
    5. Set max length (50-60 is the SEO sweet spot)
    6. Toggle “Transliterate Unicode” — converts café to cafe, 北京 to bei-jing, etc.
    7. Click Copy

    Slug generation in code

    // JavaScript (slug-friendly approach)
    function slugify(text) {
      return text
        .toLowerCase()
        .normalize("NFKD")            // decompose accents
        .replace(/[̀-ͯ]/g, "") // remove diacritics
        .replace(/[^a-z0-9\s-]/g, "")    // strip punctuation
        .trim()
        .replace(/\s+/g, "-")            // spaces to hyphens
        .replace(/-+/g, "-")             // collapse multiple hyphens
        .slice(0, 60);                   // length cap
    }
    
    slugify("Café Owners Guide!");  // "cafe-owners-guide"
    
    // Python (python-slugify package)
    from slugify import slugify
    slugify("Café Owners Guide!")    # "cafe-owners-guide"
    
    // Node (slugify package — handles 50+ languages)
    import slugify from "slugify";
    slugify("北京", { lower: true });  // "bei-jing"
    
    // PHP (WordPress's built-in)
    $slug = sanitize_title("Café Owners Guide!");

    Common slug mistakes

    • Including dates. /2024/05/best-tools/ looks dated by the next year. Either embrace it (news sites do) or omit dates and use evergreen slugs.
    • Including IDs. /post-12345-best-tools/ is the worst of both worlds — adds noise without semantic value.
    • Changing slugs after publishing. Existing inbound links break unless you set up 301 redirects. Pick the slug carefully on first publish.
    • Stuffing keywords. /best-cheap-affordable-budget-running-shoes/ reads as keyword-stuffed and Google may penalise.
    • Forgetting trailing slashes. Pick /posts/foo/ or /posts/foo as your canonical form and stick to it. Inconsistent trailing slashes confuse crawlers and cause duplicate-content issues.

    Frequently asked questions

    Should I include the year in my URL slug?

    Only if the content is genuinely time-bound (news, annual rankings, year-specific reviews). For evergreen content (how-to guides, tutorials), omit dates so the slug remains relevant. If you do include a year, plan to update or redirect the URL when the year changes.

    How long should a URL slug be?

    50-60 characters is the SEO sweet spot. Long enough to include keywords; short enough to display in mobile search snippets without truncation. 75+ characters get truncated in Google SERP.

    Should I remove stop words from my slug?

    Generally yes — they add length without adding meaning. how-to-cook-pasta beats how-to-cook-the-best-pasta-of-your-life. Exception: when removing the stop word changes meaning (rare). The tool’s “Strip stop words” toggle lets you choose per-slug.

    What if my title contains non-English characters?

    Three options: (1) transliterate to ASCII (cafécafe) — safest for global audiences; (2) keep Unicode in the URL with proper encoding (modern browsers handle this fine, but tools, CRMs, and email clients sometimes don’t); (3) use a localised slug system per language. The tool defaults to transliteration for ASCII safety.

    Can I change a slug after publishing?

    Yes, but you must set up a 301 redirect from the old URL to the new one to preserve incoming links and SEO value. Without redirects, all existing backlinks break and the page loses its accumulated ranking signal. WordPress and most CMSes have plugins to manage redirects automatically when slugs change.

    Is the slug data sent anywhere?

    No. The slug is generated in your browser using JavaScript string manipulation. The text you paste, the generated slug, and any settings stay on your device.

    Related tools and guides

     

  • HTML Minifier: Compress HTML Safely in Browser [2026]

    HTML Minifier: Compress HTML Safely in Browser [2026]

    TL;DR: An HTML minifier removes whitespace, comments, redundant attribute quotes, and (optionally) minifies inline <style> and <script> blocks. Typical pages shrink 20–35% pre-gzip. Use it on static pages, email templates, and AMP documents — but skip it on server-rendered HTML where bytes matter less than build complexity. Our free HTML minifier runs html-minifier-terser in your browser with safe defaults you can override.

    HTML is the easiest place to leave bytes on the floor. Hand-authored markup carries indentation, comments, optional closing tags (</li>, </p>), and quoted attributes that could be unquoted. A 112 KB hand-written page minifies to 78 KB (−30%); add gzip and you’re at roughly 18 KB on the wire. For a marketing landing page or an email template that ships unchanged for months, those savings compound across every visit.

    Our HTML minifier wraps html-minifier-terser — the de-facto Node.js engine since 2017 — and runs it entirely in your browser. It minifies inline CSS via csso and inline JS via Terser, both included. This guide covers what’s safe to strip, what to leave alone, and the gotchas that turn perfectly valid HTML into broken markup.

    What HTML minification removes (and the size impact)

    Transform Example Savings
    Collapse whitespace Indentation between tags 10–25%
    Remove comments <!-- ... --> 2–8%
    Drop optional tags </li> at end of <li> 1–3%
    Unquote attributes id="x"id=x 1–2%
    Drop redundant attrs type="text" on <input> <1%
    Boolean attribute collapse disabled="disabled"disabled <1%
    Minify inline CSS csso on <style> blocks 3–10% (depends on CSS)
    Minify inline JS Terser on <script> blocks 3–8% (depends on JS)

    Safe vs aggressive: which options to enable

    html-minifier-terser exposes about 30 boolean flags. Most are safe; a handful change rendering or break edge cases. Our default preset turns on these safe options:

    • collapseWhitespace — strip indentation between tags. Won’t collapse whitespace inside <pre>, <textarea>, or content marked with white-space: pre.
    • removeComments — strip <!-- ... -->. Preserves IE conditionals (<!--[if IE]>) and lines marked with <!-- ! -->.
    • removeRedundantAttributes — drops type="text", method="get", etc.
    • collapseBooleanAttributeschecked="checked"checked.
    • minifyCSS + minifyJS — minify inline blocks.

    Options to enable only with care:

    • removeOptionalTags — drops </li>, </p>, </td>. Valid HTML5 but breaks XML-strict tooling and some legacy parsers.
    • removeAttributeQuotes — saves a few bytes but breaks if an attribute value contains spaces or special characters.
    • conservativeCollapse — preserves a single space at edges where collapsing might affect rendering. Safer but smaller savings.

    How to minify HTML in your browser

    1. Open the HTML minifier
    2. Paste your HTML or drop in an .html file
    3. Pick the preset: Safe (default), Aggressive, or Email-template-safe
    4. Click Minify — output appears with before/after sizes
    5. Copy or download as .min.html

    Email-template gotchas

    HTML emails are the wild west: Outlook 2016 still parses HTML4 with quirks, Gmail strips <style> blocks under certain conditions, and Apple Mail rendering disagrees with iOS Mail in subtle ways. Aggressive minification breaks emails in ways that don’t show up in DesktopGmail but break in Outlook. Use the Email-template-safe preset, which:

    • Keeps all attribute quotes (Outlook chokes on unquoted)
    • Preserves IE conditional comments (<!--[if mso]>)
    • Doesn’t drop optional tags
    • Doesn’t minify inline CSS (some clients require expanded CSS)
    • Preserves <!--[if !mso]> and mso-* proprietary attributes

    Test minified email templates with Litmus or Email on Acid before sending; visual inspection in Gmail web won’t catch Outlook breakage.

    Common gotchas

    • Whitespace inside <pre> and <textarea> is significant. Minifiers preserve it by default; verify your output if you’ve added unusual elements with white-space: pre styling.
    • Inline templates (Vue, Handlebars, JSX) can break. Whitespace between adjacent text nodes carries meaning in some templating languages. Minify the rendered output, not the template source.
    • Attribute order changes. Some minifiers reorder attributes alphabetically. If you have CSS or JS that depends on attribute order (rare but real), turn that off.
    • JSON-LD inside <script type="application/ld+json"> is preserved. Minifiers shouldn’t touch JSON-LD content, but a buggy minifier may strip its leading whitespace and break parsing. Verify schema validates after minifying.
    • Don’t minify HTML you’ll edit later. Minified HTML is unreadable. Keep the source, generate the minified output as a build artefact, and never commit minified HTML to your repo unless that’s your only deployment artefact.
    • Multi-byte characters get corrupted by some legacy minifiers. html-minifier-terser handles UTF-8 correctly. Older “html-tidy” tools strip emoji and non-Latin characters silently.

    When NOT to use a browser HTML minifier

    For server-rendered apps (Next.js, Nuxt, Remix, SvelteKit, Astro), HTML minification is automatic in production builds. For static site generators (Eleventy, Hugo, Jekyll), it’s a single config flag. For email templates, install html-minifier-terser locally and run it as part of your build with the email-safe preset baked in. Use this browser tool for one-off pages, snippets pasted from a CMS, AMP pages prepared by hand, and email templates you edit visually.

    Frequently asked questions

    Is minified HTML still valid?

    Yes — html-minifier-terser produces valid HTML5. Even with optional-tag removal, the output passes the W3C validator. The exception is removeAttributeQuotes, which produces non-quoted attribute values that some old browsers (IE6/7) don’t handle correctly. Stick to the safe preset for maximum compatibility.

    How much will gzip add on top of HTML minification?

    Roughly another 60–70%. A 78 KB minified HTML file gzips to about 22 KB. HTML compresses extremely well because of repeated tag names and attribute values. Always serve .html with Content-Encoding: gzip or br.

    Will minification break my Schema.org JSON-LD?

    No — html-minifier-terser preserves <script type="application/ld+json"> contents intact. The JSON inside is passed through unchanged. If your schema breaks after minifying, the issue is elsewhere — usually whitespace stripping outside the script tag concatenating two adjacent script blocks.

    Can I minify HTML emails for Mailchimp or SendGrid?

    Yes, but use the email-template-safe preset. Modern email clients tolerate minified HTML, but Outlook 2016 and earlier choke on unquoted attributes and missing optional tags. Test in Litmus before sending.

    Is my HTML uploaded?

    No. The minifier runs in your browser via WebAssembly. Pasted markup never reaches our servers — useful when minifying pre-release pages, internal docs, or email templates with proprietary content.

    What’s the difference between an HTML minifier and a CSS minifier?

    HTML minifiers strip whitespace and tags from markup; CSS minifiers strip whitespace and shorten selectors inside stylesheets. Our HTML minifier also minifies inline <style> and <script> blocks, so for a single HTML file with embedded CSS/JS, one pass through the HTML minifier handles everything.

    Related tools and guides

     

  • Base64 Encoder Decoder: Text & Files in Browser [2026]

    Base64 Encoder Decoder: Text & Files in Browser [2026]

    TL;DR: A Base64 encoder/decoder converts arbitrary binary or text data to and from a 64-character ASCII representation safe to embed in URLs, JSON, email, and source code. Text and small files encode in your browser via our free Base64 tool. Use the URL-safe variant (replaces + and / with - and _) for tokens that ride through query strings.

    Base64 is everywhere: data URIs (data:image/png;base64,iVBOR…), email attachments (MIME), JWT tokens, SAML assertions, OAuth flows, the Authorization header in HTTP basic auth, embedded SVG icons in CSS, X.509 certificates wrapped in PEM. It’s not encryption — anyone can decode it — it’s a transport-safe encoding that lets binary data ride through systems that only accept ASCII text. Every developer needs to encode or decode Base64 several times a week, and most reach for an online tool because the language built-ins are awkward.

    Our Base64 encoder/decoder handles text and binary files entirely in your browser — no upload, no server roundtrip. URL-safe variant supported. This guide explains what Base64 actually does, when each variant matters, the security non-confusion (Base64 is not encryption), and the workflows that drive most “base64 encoder online” searches.

    What Base64 actually does

    Base64 takes 3 bytes (24 bits) of input and represents them as 4 ASCII characters (each carrying 6 bits of information, drawn from a 64-character alphabet of A-Z, a-z, 0-9, plus + and /). The 64th character (technically the 65th — =) is padding when the input length isn’t a multiple of 3. The result is always 4/3 the size of the input — a 30 KB image becomes 40 KB of Base64 text.

    • Standard Base64: uses A-Z a-z 0-9 + /. Output may include = padding. Right for email, MIME, most binary-in-text contexts.
    • URL-safe Base64: replaces + with - and / with _. Right for tokens, query strings, filenames — anywhere + and / have other meanings.
    • Base64 with padding stripped: some systems (JWT tokens, OAuth) strip the trailing = padding because it’s redundant when the length is known. The decoder needs to handle both padded and unpadded inputs.

    Five common Base64 use cases

    • Data URIs in CSS or HTML. Inline a small icon or font in your stylesheet to avoid an extra HTTP request: background: url("data:image/svg+xml;base64,PHN2…"). Best for assets under 4-8 KB.
    • HTTP Basic Auth. The Authorization: Basic {base64(username:password)} header. Encoded, not encrypted — always pair with HTTPS.
    • JWT token payloads. Each segment of a JWT is URL-safe Base64. Decoding reveals the header, claims, and signature without verifying authenticity.
    • Email attachments (MIME). Email transports text only; Base64 encodes binary attachments for transport.
    • Storing binary data in JSON. JSON has no native binary type. Base64 wraps the bytes as a string field.

    How to use the browser Base64 tool

    1. Open the Base64 encoder/decoder
    2. Pick a mode: Encode (text/file → Base64) or Decode (Base64 → text/file)
    3. For text: paste into the input area; the result appears live
    4. For files: drop a file into the file panel — the encoded Base64 appears immediately, with a copy button
    5. Toggle URL-safe variant if you need to embed the result in a URL or JWT-style context
    6. Click Copy or Download. Decoded files download with their original or detected MIME type

    All operations run in your browser via the standard btoa / atob primitives plus modern TextEncoder for Unicode handling.

    Base64 in code — every common language

    // JavaScript (browser)
    btoa("Hello, world!");                    // "SGVsbG8sIHdvcmxkIQ=="
    atob("SGVsbG8sIHdvcmxkIQ==");             // "Hello, world!"
    
    // JavaScript (Node) — Buffer is the standard
    Buffer.from("Hello, world!").toString("base64");
    Buffer.from("SGVsbG8sIHdvcmxkIQ==", "base64").toString();
    
    // Python
    import base64
    base64.b64encode(b"Hello, world!").decode()      # "SGVsbG8sIHdvcmxkIQ=="
    base64.b64decode("SGVsbG8sIHdvcmxkIQ==").decode()
    
    # URL-safe variant
    base64.urlsafe_b64encode(b"data?with/special").decode()
    
    // Bash
    echo -n "Hello, world!" | base64                  # SGVsbG8sIHdvcmxkIQ==
    echo "SGVsbG8sIHdvcmxkIQ==" | base64 -d           # Hello, world!
    
    // Go
    import "encoding/base64"
    base64.StdEncoding.EncodeToString([]byte("Hello"))
    base64.URLEncoding.EncodeToString([]byte("Hello"))

    Common Base64 mistakes

    • Confusing Base64 with encryption. Base64 is reversible by anyone — it’s not security. Sensitive data in Base64 is sensitive data in plaintext. Use TLS, encryption (AES, RSA), and hashing (SHA-256) for actual security.
    • Mixing standard and URL-safe variants. A token encoded URL-safe (-_) won’t decode with a standard decoder (expecting +/). Both your encoder and decoder must use the same variant.
    • Forgetting Unicode encoding. JavaScript’s btoa only handles Latin-1 characters by default. For Unicode strings, encode to UTF-8 first: btoa(unescape(encodeURIComponent(str))) or use TextEncoder.
    • Inlining huge images as data URIs. A 500 KB image becomes 670 KB of Base64 — bloats your HTML/CSS, slows initial render. Use data URIs only for assets under ~8 KB.
    • Padding handling. Some systems strip the trailing = from Base64 (notably JWT). Decoders must handle both forms or pad inputs to a multiple of 4 before decoding.

    When NOT to use Base64

    • For storing passwords or secrets. Use proper hashing (Argon2id, bcrypt) for passwords. Base64 of a password protects nothing.
    • For very large files. Base64 inflates size by 33%. Send binary data via multipart/form-data or direct binary uploads instead.
    • For data already URL-safe. If your text is already ASCII without special characters, Base64 just bloats it. Plain text passes through URL params fine after URL-encoding.
    • As a checksum. Base64 doesn’t detect corruption. Use SHA-256 for integrity verification.

    Frequently asked questions

    Is Base64 encryption?

    No. Base64 is encoding, not encryption. Anyone can decode Base64 instantly without a key. It’s the wrong tool for keeping data secret. Use real encryption (AES-GCM, RSA, libsodium) for confidentiality.

    What’s the difference between Base64 and URL-safe Base64?

    Standard Base64 uses + and / in its alphabet. These have special meanings in URLs and filenames, so URL-safe Base64 substitutes - for + and _ for /. JWT tokens, OAuth, and most modern API tokens use the URL-safe variant.

    Why does Base64 add 33% size?

    Three input bytes (24 bits) become four output characters, each storing 6 bits — a 4:3 ratio. The math is fundamental to representing 8-bit data in a 6-bit-per-character alphabet, plus padding. Total inflation is exactly 4/3 of the input.

    Can I encode a file with the browser tool?

    Yes — drop any file into the file panel. The browser reads it via the FileReader API, encodes locally, and shows the Base64 with a copy button. No upload. Works for files up to roughly 100 MB before browser memory becomes the bottleneck.

    What’s the maximum size for a data URI in CSS?

    Practically ~8 KB for a single asset. Beyond that, the bloat to your CSS/HTML outweighs the saved HTTP request. For larger assets, serve as a regular file and let HTTP/2 multiplex the request — modern browsers handle parallel asset loading efficiently.

    Is my data uploaded when I use the tool?

    No. The tool uses browser-native btoa/atob and FileReader API for files. All processing is local. Verify in DevTools Network tab — there are no requests when you encode or decode.

    Related tools and guides

     

  • RGB to HEX Converter: Convert Any Color [2026]

    RGB to HEX Converter: Convert Any Color [2026]

    TL;DR: RGB to HEX conversion takes a color expressed as three 0–255 channels (red, green, blue) and outputs a 6-digit hexadecimal code prefixed with #. rgb(99, 91, 255) becomes #635BFF. With an alpha channel, you get an 8-digit HEX: rgba(99, 91, 255, 0.5)#635BFF80. Our free RGB to HEX converter handles all common formats — RGB, RGBA, HSL, HSV, CMYK, OKLCH — with a live colour swatch, WCAG contrast scores, and named-colour matching.

    Web designers convert colours between RGB and HEX dozens of times a week. A designer hands you an RGB triplet from Figma; a stylesheet uses HEX; a UI library expects HSL; a print spec demands CMYK. Every framework picks its favourite and assumes you’ll convert the rest. Mental math works for greyscale (rgb(255,255,255) = #FFFFFF) but fails for anything in between — converting 91 to 5B in your head is a recipe for typos.

    Our RGB to HEX converter handles every direction (RGB ↔ HEX ↔ HSL ↔ HSV ↔ CMYK ↔ OKLCH), preserves alpha channels correctly, and shows a large colour preview alongside every value. Each output also includes the WCAG contrast ratio against pure black and pure white, so you can rule out colours that fail accessibility audits in one glance. This guide covers exactly how the conversion works, why 8-digit HEX matters in modern CSS, and the gotchas that turn a perfect conversion into a wrong one.

    Format reference: RGB, HEX, HSL, OKLCH

    Format Example Best for
    HEX (6-digit) #635BFF Brand colours, opaque CSS, copy-paste from Figma
    HEX (8-digit, with alpha) #635BFF80 Translucent overlays — same brevity as HEX
    RGB rgb(99, 91, 255) Programmatic generation, design tools
    RGBA rgba(99, 91, 255, 0.5) Translucent fills with explicit alpha
    HSL hsl(243, 100%, 68%) Dynamic shade adjustments (modify L only)
    HSV / HSB hsv(243, 64%, 100%) Photoshop / Sketch picker workflow
    CMYK cmyk(61%, 64%, 0%, 0%) Print specs only — never web
    OKLCH oklch(56% 0.27 270) Modern CSS, perceptually-uniform palettes

    How the math works

    RGB to HEX is a straight base-10 to base-16 conversion of three numbers, padded to 2 digits each:

    // rgb(99, 91, 255) → #635BFF
    const toHex = (n) => n.toString(16).padStart(2, "0").toUpperCase();
    const hex = `#${toHex(99)}${toHex(91)}${toHex(255)}`;
    // → "#635BFF"

    For 8-digit HEX with alpha, append a fourth pair scaled from 0–1 to 0–255: 0.5 × 255 = 127.5 → rounds to 128 → 0x80. Result: #635BFF80. Note that 8-digit HEX with alpha is widely supported (Chrome 62+, Firefox 49+, Safari 9.1+) — well over 95% of users in 2026 — so you can safely replace rgba(...) with 8-digit HEX in modern stylesheets.

    How to convert RGB to HEX in your browser

    1. Open the RGB to HEX converter
    2. Pick the colour with the visual picker, OR type a value in any format
    3. All other formats update in real time below the input
    4. Copy any result with one click; the colour preview matches what you’ll get on screen
    5. WCAG contrast scores against black and white show inline — useful for accessibility checks

    3-digit HEX shorthand and when it works

    CSS allows #FFF as shorthand for #FFFFFF, and #F0A for #FF00AA. Each digit duplicates: #ABC means #AABBCC. This works only when each channel pair has identical digits — #635BFF (no duplicate pairs) cannot be expressed in 3-digit form. The shorthand also has a 4-digit alpha variant: #FFF8 means #FFFFFF88 — an alpha of 0x88 (about 53%).

    Most minifiers expand 3-digit HEX to 6-digit during build, then the gzipped output ends up similar size. Don’t write code that depends on the format — semantically #FFF and #FFFFFF are identical.

    Common gotchas

    • HEX is case-insensitive but lowercase is conventional in CSS. #635BFF and #635bff render identically. Modern style guides (Airbnb, Google) lowercase by default; some teams uppercase for visual contrast against text.
    • Browser colors object accepts named colours. red#FF0000, cornflowerblue#6495ED. Our converter recognises all 147 CSS named colours and shows the matching name where one exists.
    • HSL is not perceptually uniform. Two HSL colours with identical L (lightness) can look very different in brightness — yellow at L=50% looks much brighter than blue at L=50%. Use OKLCH if you want perceptually-uniform palettes.
    • CMYK conversion is approximate. RGB and CMYK have different gamuts (printers can’t reproduce all RGB colours, and vice versa). Our CMYK output is a naive conversion, not an ICC-profile-based one. For print specs, pick CMYK in Adobe Illustrator with the right profile loaded.
    • Alpha precision differs. rgba(255,0,0,0.5) rounds to #FF000080, but 0.5 × 255 = 127.5 rounds up. Round-tripping #FF000080 back gives 0.502. The 1-in-256 quantisation is invisible to the eye.
    • OKLCH chroma maxes out around 0.4. Higher values either clamp to the gamut or produce out-of-gamut colours (which browsers display as the closest in-gamut equivalent). Our converter shows when an OKLCH value exceeds the sRGB gamut.

    When NOT to use a converter

    For programmatic conversion in code, use the language-native API: CSS Color Module 4 in modern browsers (CSS.color()), Color.js or chroma.js for batch conversion, or color npm for Node.js. For design tools (Figma, Sketch, Adobe XD), the built-in colour picker handles every conversion natively. Use this browser tool for one-off conversions, accessibility audits, brand-spec verifications, and learning the relationship between formats.

    Frequently asked questions

    What’s the difference between RGB and HEX?

    Same colour, different notation. RGB writes the three channels as decimal numbers (0–255 each) separated by commas. HEX concatenates the same three channels as 2-digit hexadecimal numbers prefixed with #. rgb(99, 91, 255) and #635BFF are identical to the browser.

    Can HEX represent transparency?

    Yes — 8-digit HEX includes an alpha channel as the last 2 digits. #635BFF80 is #635BFF at roughly 50% opacity. 8-digit HEX is supported in all modern browsers (Chrome 62+, Firefox 49+, Safari 9.1+) and in CSS Modules 4, so prefer it over rgba() for translucent values.

    Why does my converted HEX look slightly off?

    Probably alpha quantisation — converting rgba(R,G,B,0.5) to HEX rounds 127.5 to 128 (0x80), and back-conversion gives 0.502. The 1-in-256 step is invisible to the eye. If colours look different by more than a single shade, the issue is gamut conversion (RGB to CMYK or OKLCH out-of-gamut), not arithmetic.

    Should I use HEX, RGB, or HSL in my CSS?

    HEX for opaque brand colours (most concise). 8-digit HEX or rgba() for translucency. HSL when you want to dynamically adjust lightness with calc() or CSS variables. OKLCH for new design systems where perceptual uniformity matters. All work everywhere — pick what reads best in your codebase.

    Is my colour data uploaded?

    No. The converter runs in your browser via JavaScript. Colour values you enter never leave your device.

    What’s OKLCH and why do designers use it?

    OKLCH is a perceptually-uniform colour space (defined in CSS Color Module 4). Lightness, chroma, and hue map to how the eye perceives them — adjust L by 10% and the colour looks 10% lighter regardless of hue. HSL doesn’t have this property: yellow at L=50% looks much brighter than blue at L=50%. OKLCH is supported natively in Chrome 111+, Safari 15.4+, Firefox 113+ — production-safe in 2026.

    Related tools and guides

     

  • Barcode Generator: Code 128, EAN-13, UPC, ITF [2026]

    Barcode Generator: Code 128, EAN-13, UPC, ITF [2026]

    TL;DR: A barcode generator turns a string of digits or alphanumeric characters into a scannable bar pattern in a chosen symbology (Code 128, EAN-13, UPC-A, Code 39, ITF, MSI). The right symbology depends on what you’re encoding: EAN-13 for retail products in Europe and most of the world, UPC-A for North American retail, Code 128 for shipping labels and inventory, ITF-14 for outer cartons. Our free barcode generator renders all of these in your browser as PNG or SVG.

    Barcodes look interchangeable from a distance but they’re a small zoo of incompatible standards. Use UPC-A on a European retail product and the supermarket scanner will reject it; use Code 39 on a shipping label and your carrier’s reader may not parse it. Picking the right symbology matters more than the visual styling. Once you’ve picked, generation is mechanical: encode your data, draw the bars, optionally add the human-readable digits underneath, export.

    Our barcode generator supports 8 symbologies covering 95% of real use cases — Code 128 (the modern default), EAN-13 / EAN-8 (retail global), UPC-A / UPC-E (retail North America), ITF-14 (outer cartons), Code 39 (legacy alphanumeric), and MSI (warehouse shelving). Outputs are scalable SVG (for print) or PNG (for screens). This guide covers which symbology to pick, the data formatting rules per type, and the print-quality details that make the difference between a barcode that scans every time and one that fails 5% of the time.

    Which barcode symbology should you pick?

    Symbology Best for Data type Length
    EAN-13 Retail products globally Digits 0-9 12 + 1 check digit
    UPC-A Retail in North America Digits 0-9 11 + 1 check digit
    Code 128 Inventory, shipping, internal IDs All ASCII Variable (1–80 typical)
    ITF-14 Outer shipping cartons Digits, even count only 14 fixed
    Code 39 Government, legacy systems A-Z, 0-9, -.$/+% Variable
    EAN-8 Small retail items (where EAN-13 won’t fit) Digits 0-9 7 + 1 check
    UPC-E Compressed UPC for small packaging Digits 0-9 6 + 1 check
    MSI Warehouse shelving Digits 0-9 Variable

    If unsure: pick Code 128 for internal use (it encodes every printable ASCII character compactly), and EAN-13 / UPC-A for retail. Don’t ship a Code 39 barcode in 2026 unless a partner system specifically requires it — it’s larger and lower density than Code 128 for the same data.

    Check digits — what they are, why they exist

    EAN-13, UPC-A, ITF-14, and others end with a check digit computed from the preceding digits using the GS1 modulo-10 algorithm: weight digits alternately by 1 and 3, sum, and pick the smallest digit that makes the total a multiple of 10. This catches single-digit errors and most transposition errors at scan time. Our generator computes the check digit automatically — paste 12 digits and we add the 13th — but you can override it if you’re reproducing a specific code that uses a different scheme.

    Code 128 has internal checksums built into the symbology; Code 39 has an optional mod-43 check digit (rarely used outside government).

    How to generate a barcode

    1. Open the barcode generator
    2. Pick a symbology (Code 128 if unsure)
    3. Enter your data — invalid characters are flagged as you type
    4. Adjust width, height, and “include text below” toggle
    5. Pick PNG (for digital use) or SVG (for print and labels)
    6. Click Download — the file appears in your browser’s downloads folder

    Print quality — the X-dimension rule

    Barcode print quality is governed by the X-dimension — the width of the narrowest bar. GS1’s published spec sets the X-dimension between 0.264 mm (10 mil) and 0.66 mm (26 mil) for retail. Print at less than 0.2 mm and scanners struggle; below 0.15 mm and scans fail outright. The barcode also needs quiet zones (blank margins) of at least 10× X on each side — squeeze the barcode into a tight box without quiet zones and scanners can’t find the start/stop characters.

    For a printed product label aim for X = 0.33 mm (13 mil); for a screen-only QR/ID barcode, any size that’s at least 200 px wide on a typical phone is fine. SVG output scales without loss, so prefer SVG for anything you’ll print.

    Common gotchas

    • EAN-13 and UPC-A are nearly identical encoding-wise. A 12-digit UPC-A is a 13-digit EAN-13 with a leading zero. Many EU scanners treat UPC-A as EAN-13 with a 0 prefix; some legacy US scanners specifically reject EAN-13 with a non-zero leading digit.
    • ITF-14 requires an even number of digits. 13-digit input is invalid; the symbology pairs digits to encode them. Our generator pads with a leading zero and recomputes the check digit.
    • Code 128 has 3 modes (A, B, C). Mode C compresses pairs of digits 2:1, halving the bar count for numeric strings. Our encoder picks the optimal mode automatically — you don’t need to choose.
    • “Standard 2 of 5” and ITF aren’t the same. Standard 2/5 is a different (rare) symbology. ITF (Interleaved 2 of 5) is the modern variant used for cartons.
    • Real product barcodes need a registered GS1 prefix. If you’re putting a EAN-13 on a product to sell in supermarkets, you must purchase a company prefix from GS1 (~$30/year for a single-digit prefix, ~$2,000+ for batches). Self-generated codes have no global guarantee of uniqueness.
    • Don’t shrink barcodes to fit a tiny package. Use a smaller symbology instead — EAN-8 or UPC-E are designed for small packaging. Squeezed full-size codes fail to scan.

    When NOT to use this tool

    For mass label printing (thousands of unique codes), use a desktop label printer driver that talks to your inventory system — Zebra ZPL, Brother P-Touch, Dymo. For commercial product distribution, register a GS1 company prefix and follow GS1’s barcode placement and quality guidelines. This generator is right for inventory tags, asset labels, internal tracking, prototype packaging, classroom demos, and one-off codes for a small business.

    Frequently asked questions

    What’s the difference between a barcode and a QR code?

    Barcodes are 1D (vertical bars only) and encode 10–80 characters. QR codes are 2D (a square grid) and encode up to 4,296 characters. Use a barcode for a product SKU or shipping label; use a QR code for a URL, contact card, WiFi credentials, or rich data.

    Can I use this for retail products I’ll sell?

    You can generate the visual, but for products sold via supermarkets and major retailers you must register a company prefix with GS1 to guarantee global uniqueness. Self-generated codes are fine for internal inventory; they’re not legally required to be globally unique unless you sell through a regulated retail chain.

    Why does my printed barcode fail to scan?

    Three usual suspects: (1) X-dimension too small — the bars are below the 0.2 mm threshold, (2) missing quiet zones — scanners can’t locate the start/stop, (3) low contrast — printer toner is faded or the surface is reflective. Print at 600 DPI minimum, leave 10× X margins, use matte paper with high-contrast ink.

    Should I use PNG or SVG?

    SVG for print — vector scales without loss at any DPI. PNG for digital use where SVG isn’t supported (some POS systems, embedded devices). Generate at 4× the display size if you go PNG, to allow zoom without aliasing.

    Is my data uploaded?

    No. The generator runs in your browser. SKUs, IDs, and product numbers stay on your device — useful when codes contain confidential information.

    Can I generate batches of barcodes?

    Yes — the tool offers a “batch mode” where you paste a list of values (one per line) and download a ZIP containing one image per line. Useful for inventory labelling and small-run product runs.

    Related tools and guides

     

  • CSS Minifier: Shrink Stylesheets 30–45% in Browser [2026]

    CSS Minifier: Shrink Stylesheets 30–45% in Browser [2026]

    TL;DR: A CSS minifier strips whitespace and comments, shortens colour values (#ffffff#fff), merges duplicate @media blocks, and removes redundant rules. Typical stylesheets shrink 25–45% before gzip; gzipped they shrink 75–85% from raw. Our free CSS minifier runs csso in your browser with full support for modern CSS — custom properties, nesting, container queries, @layer, OKLCH colours.

    CSS is render-blocking by default. Until the browser downloads, parses, and applies your stylesheet, the page can’t paint a single pixel. Every kilobyte of CSS in the critical path adds latency. Minification is the cheapest fix: a 84 KB stylesheet with comments and indentation becomes a 52 KB minified file (−38%) and a 12 KB gzipped payload (−86%). For a Tailwind-based site that ships 200 KB of utility CSS, that’s a difference users notice on a 4G connection.

    Our CSS minifier uses csso (the engine behind Yandex’s stack) with optional clean-css fallback for legacy edge cases. It handles modern CSS — CSS variables, native nesting, container queries, @layer, the OKLCH colour space, and the new :has() selector — without breaking syntax. Paste any size, get instant minified output, and download or copy. This guide covers what minification does to CSS specifically, the size savings to expect, and the gotchas that turn a working stylesheet into a broken one.

    What CSS minification actually does

    Transform Example Savings
    Whitespace + comments remove all /* … */ and indentation 15–30%
    Hex shortening #ffffff#fff 2–4%
    Zero unit drop 0px0 1–2%
    Leading zero drop 0.5em.5em <1%
    Shorthand collapse margin: 0 0 0 0margin: 0 1–3%
    Selector dedupe merge two .btn{...} rules 2–8%
    @media merge two identical media queries → one block 3–10%
    Property merge border-top:0;border-right:0border:0 1–4%

    Total typical reduction: 25–45%. Hand-written stylesheets shrink more (lots of whitespace and comments); pre-minified frameworks shrink less (already optimised). Tailwind output, post-PurgeCSS, typically shrinks another 15–25% with csso on top.

    Modern CSS that minifiers used to break

    Older minifiers (clean-css 3.x and YUI Compressor) corrupt modern CSS in several ways. csso handles all of these correctly:

    • CSS custom properties: --brand: #635BFF values and var() references are preserved exactly. Old minifiers stripped fallbacks.
    • Native nesting: .card { .title { } } is preserved (modern browsers parse it natively without a preprocessor).
    • Container queries: @container (width > 400px) { … } is preserved with all syntax variants.
    • OKLCH and color-mix(): new colour formats are passed through; csso doesn’t try to “shorten” them since the format is already minimal.
    • :has() selector: the parent selector is preserved without quote-mangling.
    • @layer: cascade layer ordering is preserved exactly — never reordered.

    How to minify CSS in your browser

    1. Open the CSS minifier
    2. Paste your CSS or drop in a .css file
    3. Pick the engine: csso (default) or clean-css (legacy)
    4. Toggle options: dedupe selectors, merge @media, restructure (aggressive)
    5. Click Minify. Output appears with before/after sizes
    6. Copy or download as .min.css

    Common gotchas

    • “Restructure” is opt-in for a reason. The aggressive csso option reorders selectors that look equivalent. If your CSS relies on cascade order (later rules override earlier ones), restructuring can change which rule wins. Test the minified output visually before deploying.
    • Don’t minify a CSS file that’s imported with @import in another file. Some minifiers inline imports; csso doesn’t by default. Bundle first (PostCSS / esbuild), minify the output.
    • Vendor prefixes are preserved. Don’t expect minification to remove -webkit- prefixes — the minifier doesn’t know which browsers you target. Use Autoprefixer to add/strip prefixes based on your browserslist.
    • Source maps are essential for production debugging. Without them, every DevTools error points at line 1 column 240. Generate a .map alongside the minified file.
    • Don’t minify already-minified files. Files ending in .min.css rarely shrink more than 1–2% on a second pass. Skip them.
    • Critical CSS extraction is a different job. Minification reduces the size of all your CSS. Critical CSS extraction inlines only the rules needed for above-the-fold content. Use a tool like Critters or Penthouse for that.

    When NOT to use a browser CSS minifier

    If your build pipeline already includes Vite, Next.js, esbuild, Webpack, or Parcel, CSS minification is built in — you don’t need a separate tool. Use this browser minifier for one-off pages built without a build system, third-party stylesheets you’re embedding, snippets pasted into a CMS that doesn’t have a build step, or to inspect what csso does to a specific block of CSS. For Node automation, install csso directly (npm i -D csso-cli) and run it from a script.

    Frequently asked questions

    How much does gzip add on top of CSS minification?

    About 50% additional. A 52 KB minified CSS file gzips to roughly 12 KB. Brotli (modern CDN default) shrinks 8–15% beyond gzip. CSS responds especially well to compression because of repeated property names — always serve .css with a Content-Encoding header.

    Will minification break my Tailwind output?

    No. Tailwind’s JIT engine produces CSS that minifies cleanly with csso. Run PurgeCSS first (Tailwind does this automatically in production), then minify. Expected pipeline: Tailwind → PostCSS → cssnano/csso → gzip. Tailwind v4 includes Lightning CSS for both transformation and minification.

    Does the minifier support CSS variables and the new colour spaces?

    Yes. csso preserves CSS custom properties, var() references with fallbacks, OKLCH, OKLab, color-mix(), and relative-colour syntax exactly. It won’t try to shorten values it doesn’t fully understand — safer than aggressive optimisation.

    Can I minify SCSS or Less directly?

    No — minify only after compilation. SCSS and Less must compile to plain CSS first (via Sass, Dart Sass, or Less), then run through the minifier. Some build tools chain these automatically; for one-off files, paste the compiled output here.

    Is my CSS uploaded?

    No. csso runs in your browser via WebAssembly. Stylesheets are never uploaded — useful for proprietary or pre-release styles.

    What’s the difference between minify and prettify?

    Opposite jobs. Minify removes whitespace to shrink size for production. Prettify (CSS Formatter) adds whitespace and indentation for readability. Use a formatter when you’re editing; use a minifier as the final step before deploy.

    Related tools and guides

     

  • Random Name Picker & List Randomizer Online [2026]

    Random Name Picker & List Randomizer Online [2026]

    TL;DR: A random name picker (or list randomizer) shuffles a list and either returns the full shuffled order or pulls a single random pick. The fair algorithm is the Fisher–Yates shuffle with a cryptographic random source — every input has equal probability of every output position. Our free list randomizer uses crypto.getRandomValues (cryptographically secure) and produces a shareable result URL so participants can verify the draw was honest.

    Picking a winner sounds simple until something goes wrong. A naive shuffle (sort with Math.random() - 0.5) is biased — some positions are 1.5–2× more likely than others — and you wouldn’t notice the bias unless you ran 10,000 trials. A weak random source means a savvy participant can, in principle, predict the outcome from prior draws. For a giveaway, raffle, or roommate chore wheel, neither is acceptable.

    Our list randomizer uses Fisher–Yates with the browser’s crypto.getRandomValues API — the same RNG used to generate cryptographic keys. The shuffle produces uniformly random results, and a shareable result URL lets you prove which order came out and when. This guide explains the fair-shuffle algorithm, the bias trap to avoid, and the use cases where a list randomizer is exactly the right tool.

    Use cases — where a randomizer fits

    Use case What you randomize Why fair matters
    Giveaway / raffle List of entrants → 1 winner Legal in most jurisdictions; bias = liability
    Team standup order List of teammates → speaking order Same person speaking last every day = morale issue
    A/B test variant assignment User IDs → variant A or B Biased assignment ruins the experiment
    Tournament bracket seeding List of players → bracket position Predictable seed = exploitable
    Classroom cold-call Roster → pick one student Equity — same students shouldn’t get picked
    Chore / pairing rotation List of people → assignment Reduces “always me” complaints

    The Fisher–Yates shuffle (and the bias trap to avoid)

    Fisher–Yates is the canonical unbiased shuffle. Walk the array from the last index down to the first; for each index i, pick a random index j in [0, i] and swap arr[i] with arr[j]. After one pass, every permutation is equally likely. It’s O(n) time and uses O(1) extra memory. Our randomizer implements it with crypto.getRandomValues for the random index, not Math.random().

    function fairShuffle(arr) {
      const a = [...arr];
      for (let i = a.length - 1; i > 0; i--) {
        const buf = new Uint32Array(1);
        crypto.getRandomValues(buf);
        const j = buf[0] % (i + 1);
        [a[i], a[j]] = [a[j], a[i]];
      }
      return a;
    }

    The trap: sorting with arr.sort(() => Math.random() - 0.5) looks shuffle-ish but is provably biased. Different JS engines use different sort algorithms (V8 uses Timsort, JavaScriptCore uses MergeSort) and the comparator is inconsistent — the same pair returns different orderings on different calls. Tests show this approach favours the input order; some positions are 2× more likely than uniform. Never use sort-with-random for fairness-critical shuffling.

    How to randomize a list in your browser

    1. Open the list randomizer
    2. Paste your list (one item per line)
    3. Pick output: Shuffled order, Pick 1 winner, or Pick N
    4. Optional: set a seed for reproducible results (useful for “audit me later” draws)
    5. Click Shuffle — output appears with a shareable URL
    6. Copy the URL to send participants the verifiable result

    Seeded vs cryptographic shuffles — when to use which

    Default mode uses crypto.getRandomValues — non-deterministic, unpredictable, the right pick for live giveaways and competitions. Seeded mode uses a deterministic PRNG (xoroshiro128+) keyed off a string you provide. Same seed plus same input always produces the same output. Use seeded mode when you want to:

    • Audit later. Announce the seed in advance (“we’ll shuffle with seed 2026-01-launch at 5pm”). Anyone can re-run the shuffle later and verify the result.
    • Reproduce a result for testing. Useful for QA, classroom demos, or replaying a competition.
    • Coordinate across devices. Same seed on two laptops produces the same random pairing without communication.

    Don’t use seeded mode for high-stakes giveaways unless the seed is committed to publicly before the entry list is finalised — otherwise an organiser can choose a seed to favour a friend.

    Common gotchas

    • Modulo bias. Naive code does buf[0] % (i + 1) which is slightly biased when i + 1 doesn’t divide 2³². For lists under 1,000 items the bias is negligible (less than 1 in 4 million); for cryptographic uses, our randomizer rejects values above the bias threshold and resamples.
    • Duplicate entries. If your list has duplicates and you pick 1 winner, the duplicates increase the duplicate’s odds linearly. Dedupe first if you want one entry per person.
    • Whitespace trimming. “Maya ” (trailing space) and “Maya” are different entries by default. Our tool offers a “trim and dedupe” toggle to merge them.
    • Big lists. Lists of 1,000+ entries shuffle instantly. 100,000+ entries take a few hundred milliseconds — still real-time but the UI may briefly stall.
    • Live-stream rendering. If you’re showing the shuffle on a Twitch / Zoom screen, use the “animated reveal” mode — the result is determined first, then the items are revealed one at a time so spectators see a draw they can watch unfold.

    When NOT to use this tool

    For high-value lotteries, regulated giveaways, or anything where the outcome is legally binding, use a service that produces a notarised audit trail (Random.org’s signed-result API, or a third-party like Vlogging Heroes Sweepstakes). A free browser tool is great for community giveaways, classroom picks, and team rotations — it’s not a courtroom-grade randomness oracle. For programmatic use inside a Node.js script, use the standard library directly (crypto.randomInt) rather than reaching for an online tool.

    Frequently asked questions

    Is this random enough for a giveaway?

    For most community giveaways, yes — it uses crypto.getRandomValues, the same RNG behind cryptographic key generation. The output is unpredictable and uniform. For regulated lotteries with a legal audit trail, use a notarised service like Random.org’s signed API.

    How does the shareable result URL work?

    The full input list, the seed (if any), and the result are encoded in the URL. Anyone who opens the URL sees the same list and the same shuffled output, so participants can verify nothing was edited after the draw. The URL contains the data — there’s no server-side state.

    Can I run a shuffle that’s reproducible?

    Yes — pick “Seeded” mode and provide a seed string. Same seed plus same input list always produces the same output. Useful for classroom demos and for audited draws where the seed is announced in advance.

    What’s the maximum list size?

    Effectively your browser’s memory. Lists of 100,000+ items work but the page can briefly stall during shuffle. For most giveaways and team uses (a few hundred items at most), shuffle is instant.

    Is my list uploaded?

    No. The randomizer runs in your browser. Lists, seeds, and results are never uploaded to our servers — useful when the entrant list contains email addresses or other personal data you don’t want to share.

    What’s wrong with sorting an array with Math.random() - 0.5?

    It’s provably biased. The comparator is inconsistent (the same pair can return different orderings on different calls), which violates sort’s preconditions. Real test runs show some positions are 2× more likely than uniform. Use Fisher–Yates instead — it’s two lines longer and actually fair.

    Related tools and guides

     

  • Blur Face Online: Photo Censor in Browser [2026]

    Blur Face Online: Photo Censor in Browser [2026]

    TL;DR: A photo censor tool covers sensitive parts of a photo — faces, license plates, addresses, screen content — with one of three opaque overlays: pixelation (mosaic blocks), gaussian blur, or black bar. Use a black bar for legal redaction, pixelation for casual face blurring, blur only when readability of the underlying region doesn’t matter. Our free photo censor runs in your browser, supports all three modes, and strips EXIF metadata from the export so location and camera data don’t leak.

    Posting a photo online without thinking about who’s in it has become a privacy concern even for casual users. A vacation snap shows a stranger’s child clearly enough to identify them. A street photo includes a license plate. A screenshot of a calendar exposes a colleague’s home address. The fix is mechanical: cover the sensitive region with an opaque overlay before publishing. Done in two minutes; the alternative is removing the photo after someone complains.

    Our photo censor handles all three common censoring modes — pixelate, blur, black bar — and lets you brush, drag a rectangle, or click a face for an automatic ellipse. Files never upload — the photo loads into your browser, gets edited locally, and exports with EXIF metadata stripped. This guide covers when to use which mode, the irreversibility of pixelation vs blur, and the photographic gotchas (low-resolution faces, low-blur radius) that have leaked private information in the past.

    Censor mode comparison — and which to actually use

    Mode Reversible? Best for
    Black bar No Legal redaction, license plates, sensitive text
    Pixelate (block 12+) No (irreversible at high enough block size) Faces in social photos, casual blurring
    Gaussian blur Partially (low blur is recoverable) Aesthetic blurring where a black bar would clash
    Solid color No Branded redactions, dark backgrounds
    Sticker / emoji overlay No Casual social posts, fun reveals

    The pixelation problem — when blurring isn’t enough

    Light pixelation can be reversed. Researchers at Cornell in 2016 demonstrated that “mosaic” pixelation with a small block size can be reverse-engineered using machine learning to identify the original face — particularly if you have other photos of the same person to train on. The defence is simple: use a large enough block size that the original information is genuinely destroyed.

    • Block size 4–8: trivially reversible. Don’t use for privacy.
    • Block size 12–18: safe for casual social posts; very hard to reverse without targeted ML.
    • Block size 24+: unrecognisable; safe for sensitive contexts.
    • Black bar: impossible to reverse — the data is gone, not blurred.

    For genuinely sensitive content (legal redaction, evidence handling, witness protection), use a black bar. For “I don’t want this person identified by a casual viewer”, pixelation at block 18 is enough.

    How to censor a photo in your browser

    1. Open the photo censor
    2. Drop your image (JPG, PNG, WebP, HEIC supported)
    3. Pick a mode: Pixelate, Blur, Black bar, Color block, or Sticker
    4. Use the rectangle tool, brush, or “click to detect face” mode to select the region
    5. Adjust block size or blur radius — preview updates live
    6. Click Export. The exported image has EXIF metadata stripped (no GPS, camera serial, or timestamp)

    EXIF metadata — the hidden privacy leak

    Every JPG and HEIC photo from a phone or camera includes EXIF metadata: latitude/longitude (if location was on), camera model, lens, exposure settings, sometimes the camera’s serial number. A photo posted to a forum or sent in an unencrypted message can leak the exact GPS coordinates of where it was taken. Pixelating a face does nothing about EXIF.

    Our exporter strips EXIF by default — the saved image has no location, no camera serial, no timestamp beyond the file’s own modified time. If you want to keep EXIF (e.g. for archival), toggle “Preserve EXIF” before export. Most platforms (Twitter, Discord, Reddit) strip EXIF on upload anyway; some (Slack file shares, email attachments, direct downloads) do not.

    Common gotchas

    • Low-resolution selections leak through pixelation. If your photo is 4000×3000 and the face is 200×200 pixels, pixelation at block 18 turns that face into 11×11 visible blocks — recognisable to anyone who knows the person. Use block 24+ or scale up the source image first.
    • Reflections and shadows. Censoring a face but leaving a reflective surface (window, mirror, sunglasses) where the face is also visible defeats the purpose. Censor every visible instance.
    • Tattoos, scars, and unusual clothing identify people. A face-blurred photo where the subject has a distinctive tattoo or coat is still identifiable to anyone who knows them. Consider blurring or cropping those features too.
    • License plates have a smaller resolution than faces. A car plate at 80×30 pixels needs a smaller block size to look natural while still being unreadable — block 6–8 typically. Blurring a plate by mistake at face-block-size washes out the whole car.
    • Screen content reflected on a face. Photos of someone looking at a phone often reveal app content reflected on their glasses. The pixelation needs to cover both the screen and the eyes.
    • Don’t rely on overlay alpha. A semi-transparent blur overlay still passes through detail. Use full-opacity overlays for any actual privacy protection.

    Legal context: when redaction is required

    Several scenarios require censoring before publication:

    • EU GDPR: photos showing identifiable people require their consent for publication — censoring removes the identifiability.
    • HIPAA (US healthcare): patient photos must redact 18 specific identifiers including face, full-body view, distinctive marks, and any identifiers in background text.
    • Court-ordered redaction: evidence photos in some jurisdictions must redact identifying information of minors, witnesses, or jurors.
    • Press ethics: news organisations often blur the faces of bystanders, accident victims, and minors — a black bar or full pixelation, never a thin blur.

    For any legal-grade redaction, use the black bar mode. Pixelation is partial protection at best; lawyers and regulators want the data gone, not just hidden.

    When NOT to use this tool

    For redacting text in PDFs, use a PDF-aware redaction tool — pixelating text in a PDF doesn’t remove the underlying text from the PDF stream, so the redacted text is recoverable by anyone with a PDF reader. For batch automation (censoring 100s of photos with the same regions), use a Python script with OpenCV or Pillow. For video face-blurring (e.g., bystanders in a YouTube vlog), use a video editor with face-tracking — this tool is for static images only.

    Frequently asked questions

    Is pixelation reversible?

    Light pixelation (block 4–8) can be reverse-engineered using ML models, especially if other photos of the same subject exist. Block 18+ is safe for social use; block 24+ is unrecognisable. For genuinely sensitive content (legal redaction), use a black bar — the underlying data is gone, not just hidden.

    Does censoring strip EXIF data?

    Yes by default — the exported image has no GPS coordinates, camera serial, or original timestamp. Toggle “Preserve EXIF” before export if you want to keep that metadata (rare; usually a privacy mistake).

    Can I use this for legal redaction?

    For legal-grade redaction, use the black bar mode — the underlying pixel data is replaced, not transformed. Pixelation and blur are partial protections at best. Always check with a legal professional for high-stakes redaction (court evidence, regulated healthcare records).

    What’s the difference between blur and pixelate?

    Blur smooths the region using a gaussian filter; pixelate replaces it with a mosaic of solid blocks. Blur looks more natural in photos; pixelate looks more “censored” but is harder to reverse-engineer at high block sizes. For privacy, pixelate at block 18+ wins; for aesthetic blurring, gaussian blur looks better.

    Is my photo uploaded?

    No. The censor runs in your browser using the canvas API. The photo is loaded into a blob URL in your tab and never leaves your device. The exported image is generated locally — you can verify with DevTools’ Network tab.

    Can the tool detect faces automatically?

    Yes — toggle “Auto-detect faces” and the tool runs an in-browser face detection model on the image. Detected faces appear as ellipses you can accept, edit, or remove. Detection is good but not perfect; always verify each face is covered.

    Related tools and guides

     

  • HTML Formatter: Beautify HTML with Prettier [2026]

    HTML Formatter: Beautify HTML with Prettier [2026]

    TL;DR: An HTML formatter (or “HTML beautifier”) takes minified, copied, or messy HTML and reformats it with consistent indentation, line wrapping, and attribute alignment. Use it on copied HTML you need to read or edit, AI-generated markup, or scraped pages. Our free HTML formatter uses Prettier 3 in your browser with full support for HTML5, Vue, Svelte, Angular, and Handlebars templates.

    Reading minified HTML is like reading a one-line essay — every tag and attribute is jammed together with no visual structure. Try to debug a layout issue or insert a new element and you spend more time finding your place than fixing the bug. A formatter restores the structure: each block-level element on its own line, nested elements indented, long attribute lists wrapped, and closing tags aligned with their opens.

    Our HTML formatter runs Prettier 3 in your browser. It auto-detects HTML5, Vue single-file components, Svelte, Astro, Angular, and Handlebars templates. Configurable: indent width, attribute-per-line wrap threshold, void-element style (<br /> vs <br>), and whether to wrap long lines. Paste any size, get clean output, copy or download.

    Prettier HTML options that matter

    Option Default When to change
    printWidth 80 100–120 if you have many attributes per element
    tabWidth 2 4 only if matching legacy code
    htmlWhitespaceSensitivity “css” “strict” if rendering depends on inline whitespace
    singleAttributePerLine false true for very wide attribute lists
    bracketSameLine false true to keep > at end of last attribute line
    endOfLine “lf” “crlf” only for Windows-only repos

    The whitespace-sensitivity setting (the option you’ll actually want to think about)

    HTML treats whitespace inconsistently. Inside a <p>, multiple spaces collapse to one. Inside a <pre>, every space is preserved. Between two inline elements (<span>a</span> <span>b</span>), the space between affects layout. Prettier’s htmlWhitespaceSensitivity option controls how aggressively the formatter rearranges whitespace:

    • “css” (default): respect CSS display defaults. Block-level elements get their own lines; inline elements stay on the same line where whitespace would matter. Best for most modern pages.
    • “strict”: never break a line where doing so would add or remove whitespace that affects rendering. Safest but produces longer lines.
    • “ignore”: format aggressively, ignoring the impact on rendering. Use only if you control the CSS and know your inline elements have white-space rules that override the default.

    Most pages format cleanly with the default. If you see layout shifts after formatting, switch to “strict” and reformat.

    How to format HTML in your browser

    1. Open the HTML formatter
    2. Paste your HTML or drop in a .html file
    3. Pick the parser (auto-detect usually works): html, vue, angular, handlebars, svelte
    4. Adjust print width and tab width to match your project
    5. Click Format — output appears with syntax highlighting
    6. Copy or download

    Templating-language support

    Prettier handles plain HTML, but real codebases often have templating syntax mixed in. Prettier 3 supports:

    • Vue: single-file components (.vue) with <template>, <script>, <style> blocks formatted independently.
    • Svelte: .svelte files including {#if} / {#each} blocks and reactive declarations.
    • Angular: *ngIf, *ngFor, and binding syntax ([prop], (event)) preserved.
    • Handlebars / Mustache: {{…}} and {{#each}} blocks indented like HTML elements.
    • Astro: via the prettier-plugin-astro plugin.

    For JSX (React), use the JavaScript Formatter instead — JSX lives in JS files and the JS parser handles both.

    Common gotchas

    • Whitespace inside <pre> and <textarea> is preserved. Prettier doesn’t touch their content. If yours looks wrong, the issue was already in your source.
    • Self-closing void elements: Prettier 3 outputs <br> (HTML5 default) not <br /> (XHTML). To force XHTML style, post-process or use a different tool — there’s no built-in option in Prettier 3.
    • Comments above tags get attached to them. Prettier may move comments slightly to keep them tied to the right element. Usually fine; occasionally surprising.
    • Custom Web Components are formatted like regular HTML elements. A <my-button> with attributes wraps the same way <button> does. No special handling needed.
    • Don’t format AI-generated HTML and ship it without checking. AI tools sometimes produce <div>…<span>…</div> with mismatched tags; the formatter happily produces beautifully indented broken HTML. Validate with the W3C validator after formatting.
    • Inline event handlers stay inline. Inline on* attributes (on​click, on​load) aren’t reformatted. Use external script tags for anything non-trivial.

    When NOT to use a browser HTML formatter

    For a real codebase, install Prettier locally (npm i -D prettier), commit a .prettierrc, and configure your editor to format on save. That eliminates formatting drift between developers. Use this browser tool for one-off snippets, copied HTML from a CMS or AI assistant, scraped markup you need to inspect, and pages built without a build pipeline. Don’t run the formatter on minified production HTML and re-deploy — keep source and minified output as separate artefacts.

    Frequently asked questions

    What’s the difference between an HTML formatter and a beautifier?

    Same thing, different name. “Formatter” is the modern term (Prettier, dprint); “beautifier” is older (jsbeautify, HTML Tidy). Both reformat messy or minified markup into readable, indented output.

    Can I format Vue, Svelte, or Astro components?

    Yes. Prettier 3 handles Vue single-file components, Svelte files, Angular templates, and Astro components natively. Auto-detection picks the parser from file extension; you can override manually for paste-mode input.

    Will formatting change how my page renders?

    With the default htmlWhitespaceSensitivity: "css", no — Prettier respects CSS display rules and only adds whitespace where it doesn’t affect rendering. Edge cases involving custom white-space CSS may need htmlWhitespaceSensitivity: "strict" to be safe.

    Can I unformat (minify) HTML with this tool?

    No — formatting and minifying are opposite operations. For minification, use the HTML Minifier. Format while editing; minify before deploying.

    Is my HTML uploaded?

    No. Prettier runs in your browser via WebAssembly. Pasted markup never reaches our servers — useful for proprietary or pre-release pages.

    Can I save my Prettier config?

    Yes. Settings persist in your browser’s localStorage between sessions. There’s also a “Copy as .prettierrc” button that exports your settings as JSON ready to drop into a project root.

    Related tools and guides