devutilia is a static, browser-only toolkit. This document describes the current data handling of the site and of every tool in it; it is a technical description, not a substitute for advice about your own privacy or compliance obligations. The sections below apply to every tool; the per-tool sections at the end add each tool's specifics.
This English text is the authoritative version. A Simplified Chinese translation, PRIVACY.zh-CN.md, is provided for convenience; where the two differ, the English text prevails.
Content you type, paste, or open is processed inside your browser. Processing normally runs in a Web Worker in the same browser; a limited synchronous fallback can perform the same processing on the main browser thread.
No tool uploads content to an application server. Runtime network requests are limited to the static first-party files needed to load the site, including each tool's Worker.
The site is served with a Content Security Policy, so the promises above do not rest on the code alone: the browser itself refuses what the policy forbids. connect-src 'self' leaves no origin a page could send content to, by fetch, XMLHttpRequest, sendBeacon, or a WebSocket; img-src and default-src keep a request for a remote image or font from carrying content in its URL; form-action and base-uri are 'none', so no form submission or rewritten base URL can take content off the page; script-src admits only this site's own scripts and the hash of the small theme script each page carries, so an injected script does not run. Responses also carry Referrer-Policy: no-referrer, X-Content-Type-Options: nosniff, Cross-Origin-Opener-Policy: same-origin, and a Permissions-Policy that denies the device APIs the toolkit never asks for.
Inline styles remain allowed, because the editor mounts its themes as the text of a <style> element. A style cannot make a network request the directives above do not already forbid.
Each tool uses its own key in the current tab's sessionStorage for best-effort refresh recovery. A versioned snapshot contains content only when its normalized UTF-8 size is at most the tool's limit: 2 MiB unless the tool's section below says otherwise. When content exceeds that limit, recovery is disabled for it and an older snapshot is removed. Clear removes the snapshot immediately.
sessionStorage is normally scoped to a browser tab, but browser crash recovery or tab-restore features may preserve it after the tab is closed. Private-browsing behavior and storage retention depend on the browser. Do not rely on closing a tab as the only way to remove sensitive content; use Clear when a tool offers it and follow your browser's storage controls when needed.
localStorage is used only for optional locale, theme, and navigation overrides, shared by every tool. Content and large-document consent are not stored there.
Sending content to another devutilia tool keeps it in this tab's session storage only until the other tool opens; it never enters a URL. The envelope is stored under the sessionStorage key devutilia:handoff:v1, is limited to 2 MiB, is removed the moment the receiving tool reads it, and is discarded unread after 60 seconds.
A tool writes to the clipboard only after you choose Copy. If clipboard access fails, it selects the editor content and asks you to use the browser or operating-system copy command.
Download creates a local browser Blob after you choose Download. Whether and where the resulting file is saved is controlled by your browser and operating system.
The site includes no:
No tool evaluates content as executable code.
Application URLs, request URLs, request bodies, request headers, console messages, and production error details do not include content. User-facing errors use stable error categories and locations rather than source text. Content is rendered in a tool's editor and views because displaying it locally is the purpose of the tool.
The in-app privacy-policy link opens the copy of this document that the site publishes on its own privacy/ page, rendered from this file when the site is built. The link itself contains no content and stays on the site.
The site is static files served by Cloudflare Pages, which terminates the connection and therefore receives each request: its IP address, the URL asked for, the User-Agent, and the time. That is true of any host, and it is the part of using this site that is not confined to your browser. What a request does not carry is content: nothing you type, paste, or open enters a URL, a request body, or a request header, so none of it reaches the host or appears in its logs. Cloudflare's own handling of that request data is governed by its terms and documentation rather than by this document.
No analytics beacon, tag manager, or telemetry script is served with the site, and the Content Security Policy described above would refuse one.
JSON Ease parses, formats, minifies, and searches JSON in this browser. Refresh recovery uses the sessionStorage key json-ease:session:v2, and no JSON is written to localStorage.
Parsing, formatting, minifying, tree projection, and search run in JSON Ease's Web Worker or its synchronous fallback. When the text is not valid JSON, the same worker also runs JSON Unwrap's detection on it locally to offer a decode stack; nothing changes the document until Unwrap is chosen, and Adjust in JSON Unwrap uses the same-tab handoff described above. The refresh-recovery snapshot under json-ease:session:v2 contains the source only when its normalized UTF-8 size is at most 2 MiB. Large-document consent is held in memory only. Download creates a local Blob named from the imported filename or json-ease.
JSON Unwrap detects and reverses escaping, quoting, transport encodings, and nested JSON strings in this browser, and can wrap edited JSON back into its original form. Refresh recovery uses the sessionStorage key json-unwrap:session:v2 for the input and the decode stack, never the output, and no content is written to localStorage.
Detection, replay, and wrapping run in JSON Unwrap's Web Worker or its synchronous fallback. The refresh-recovery snapshot under json-unwrap:session:v2 contains the input and the decode stack only when the input's normalized UTF-8 size is at most 2 MiB. Base64 and URL decoding happen locally; the tool never fetches anything a decoded value might point to. Opening the result in another tool uses the same-tab handoff described above.
JSON Diff compares two JSON documents in this browser and produces the findings, highlights, and JSON Patch locally. Refresh recovery uses the sessionStorage key json-diff:session:v2 for both inputs, their decode stacks, and the comparison options, and no content is written to localStorage.
Comparison, patch application, and the line diff run in JSON Diff's Web Worker or its synchronous fallback; the same worker runs JSON Unwrap's detection on a side that is not valid JSON. The refresh-recovery snapshot under json-diff:session:v2 holds both inputs only when together they are at most 2 MiB. Download creates a local Blob named from the imported filenames or left-to-right.patch.json. Opening a side or the patch in another tool uses the same-tab handoff described above.
A token is a credential: the key you paste stays in memory only and is never stored, sent to another tool, copied, or downloaded; Clear removes the token from this tab.
JWT Inspector decodes JSON Web Tokens, explains their claims, and verifies signatures in this browser with the key you paste. Refresh recovery uses the sessionStorage key jwt:session:v2 for the pasted text and the chosen token only when the text is at most 1 MiB; a browser's own password manager may still offer to remember the secret field, which the tool never asks it to. No content is written to localStorage.
Decoding runs on the page itself without a Web Worker; signature verification uses the browser's Web Crypto with the key imported as non-extractable, so it needs a secure context (HTTPS or localhost). The tool never fetches the key locations a token names (jku, x5u) or an issuer's discovery document. Opening the header or the payload in another tool uses the same-tab handoff described above; the token and its signature are never part of an envelope.
JSON Schema validates a JSON document against a JSON Schema, or generates a schema from the document, in this browser. Refresh recovery uses the sessionStorage key json-schema:session:v2 for both inputs, their decode stacks, and the options, only when together they are at most 2 MiB; no content is written to localStorage.
Validation and generation run in JSON Schema's Web Worker or its synchronous fallback; the same worker runs JSON Unwrap's detection on a side that is not valid JSON. The tool never fetches the locations a schema names in $schema, $ref, or $id: the four supported meta-schemas are bundled, and a reference into another document is reported as not followed. Download creates a local Blob named from the imported document's filename or document.schema.json. Opening a side in another tool, or sending the document to JSON Diff, uses the same-tab handoff described above, with the slot it should land in.
Avro Decode never contacts a Schema Registry: a Confluent message's schema id is shown, never resolved, and nothing a schema or a message names is ever fetched.
The bytes of a file you open are never stored: they stay in this tab and its worker until you remove the file or leave the page, so a refresh asks for the file again.
Avro Decode decodes Apache Avro binary data to JSON in this browser. Refresh recovery uses the sessionStorage key avro:session:v1 for the pasted text, the schema, the options, and a flag saying a file was open, only when the two texts together are at most 2 MiB; the file's bytes are never part of it, and no content is written to localStorage.
Reading the bytes, parsing the schema, and decoding run in Avro Decode's Web Worker or its synchronous fallback, which the tool falls back to for inputs at or below 1 MiB; the decoded JSON's tree is built on the page itself. Download creates a local Blob named from the opened file's name or an imported schema's filename, or output.json and schema.avsc without either. Sending the decoded JSON to JSON Ease, a JSON Diff side, or JSON Schema, and the schema to JSON Ease, uses the same-tab handoff described above.