Modern APIs, configuration files, databases and message queues all deal in JSON. But raw JSON is schema-less by nature — any key can hold any value, and there's nothing to stop a consumer from sending {"age": "twenty-five"} when you expect {"age": 25}. JSON Schema solves this by providing a vocabulary for describing the structure, types and constraints of JSON documents. A JSON Schema generator takes your sample JSON and automatically produces a Schema that describes it — saving hours of manual schema writing.
This guide covers everything a developer needs to know: what JSON Schema is and how the draft versions evolved, a complete keyword reference with real examples, how schema generation works algorithmically, how to validate data with advanced constraints like required, enum, pattern and additionalProperties, how JSON Schema integrates with OpenAPI/Swagger and TypeScript ecosystems, common pitfalls and how to fix them, and when to use JSON Schema vs TypeScript interfaces vs Zod runtime validators.
Generate JSON Schema from Your JSON
Paste any JSON object and get a complete, valid JSON Schema instantly. Supports Draft 4, 7 and 2020-12. Free, no login required.
What is JSON Schema and Why Do Developers Use It?
JSON Schema is a declarative language for annotating and validating JSON documents. It is defined by the IETF and has gone through several draft versions — the current stable release is Draft 2020-12 (also called Draft 10).
What JSON Schema Does
- Validation — Verify that JSON data conforms to expected structure at runtime
- Documentation — Self-documenting API contracts, readable by humans and machines
- Code generation — Generate TypeScript interfaces, Python dataclasses, Go structs from schemas
- UI generation — Tools like react-jsonschema-form render forms automatically from schemas
- IDE support — JSON and YAML files with an associated schema get autocomplete and inline errors
Draft Version History
| Draft | Year | Key Changes | Status |
|---|---|---|---|
| Draft 4 | 2013 | Foundation: type, properties, required, allOf/anyOf/oneOf | Legacy (still widely used) |
| Draft 6 | 2017 | Added: const, contains, propertyNames, examples | Legacy |
| Draft 7 | 2018 | Added: if/then/else, readOnly, writeOnly, $comment | Common in tools |
| Draft 2019-09 | 2019 | $recursiveRef, $defs, unevaluatedProperties | Supported |
| Draft 2020-12 | 2020 | $dynamicRef, prefixItems (for tuples), improved $ref | Current recommended |
A Simple Schema Example
// Sample JSON data:
{
"id": 42,
"username": "jsmith",
"email": "jsmith@example.com",
"age": 30,
"active": true,
"roles": ["admin", "editor"]
}
// Generated JSON Schema (Draft 2020-12):
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/schemas/user.schema.json",
"title": "User",
"description": "A user account object",
"type": "object",
"properties": {
"id": {
"type": "integer",
"description": "Unique user identifier"
},
"username": {
"type": "string",
"minLength": 3,
"maxLength": 30,
"pattern": "^[a-zA-Z0-9_]+$"
},
"email": {
"type": "string",
"format": "email"
},
"age": {
"type": "integer",
"minimum": 0,
"maximum": 150
},
"active": {
"type": "boolean"
},
"roles": {
"type": "array",
"items": { "type": "string" },
"uniqueItems": true
}
},
"required": ["id", "username", "email"],
"additionalProperties": false
}
JSON Schema Data Types and Keywords: Complete Reference
JSON Schema keywords fall into several categories. Here is the authoritative reference for Draft 2020-12.
Core Data Types
| Type | JSON Equivalent | Example Values | Type-Specific Keywords |
|---|---|---|---|
string | String | "hello", "2026-03-19" | minLength, maxLength, pattern, format |
integer | Number (whole) | 42, -7 | minimum, maximum, exclusiveMinimum, multipleOf |
number | Number (any) | 3.14, 42 | minimum, maximum, multipleOf |
boolean | Boolean | true, false | — |
array | Array | [1, 2, 3] | items, prefixItems, minItems, maxItems, uniqueItems, contains |
object | Object | {"key": "val"} | properties, required, additionalProperties, patternProperties, minProperties |
null | null | null | — |
Universal Keywords (Apply to All Types)
{
"type": "string",
// Metadata
"title": "User Email",
"description": "The user's primary email address",
"default": "user@example.com",
"examples": ["alice@example.com", "bob@company.org"],
"$comment": "Validated against RFC 5322",
// Enumeration
"enum": ["active", "inactive", "pending"],
// Constant value
"const": "active",
// Combining schemas
"allOf": [{ "$ref": "#/$defs/BaseEmail" }],
"anyOf": [{ "type": "string" }, { "type": "null" }],
"oneOf": [{ "format": "email" }, { "format": "uri" }],
"not": { "type": "integer" }
}
String Keywords
{
"type": "string",
"minLength": 8, // Minimum character count
"maxLength": 128, // Maximum character count
"pattern": "^[A-Z]{2}\d{6}$", // Regex pattern
"format": "email" // Semantic format hint
// Formats: email, uri, uri-reference, uuid, date, time,
// date-time, duration, ipv4, ipv6, hostname, byte, binary
}
Object Keywords
{
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" }
},
"required": ["name"], // These keys MUST be present
"additionalProperties": false, // No keys outside properties allowed
// OR:
"additionalProperties": { "type": "string" }, // Extra keys must be strings
"patternProperties": {
"^S_": { "type": "string" }, // Keys starting with S_ must be strings
"^I_": { "type": "integer" } // Keys starting with I_ must be integers
},
"minProperties": 1, // At least 1 key required
"maxProperties": 10, // At most 10 keys allowed
"propertyNames": {
"pattern": "^[a-zA-Z_][a-zA-Z0-9_]*$" // All key names must match
}
}
Array Keywords
{
"type": "array",
// All items same schema:
"items": { "type": "string" },
// Tuple (positional types, Draft 2020-12):
"prefixItems": [
{ "type": "string" }, // First item: string
{ "type": "integer" }, // Second item: integer
{ "type": "boolean" } // Third item: boolean
],
"items": false, // No additional items beyond prefixItems
"minItems": 1,
"maxItems": 100,
"uniqueItems": true, // All items must be unique
"contains": { // At least one item must match
"type": "integer",
"minimum": 0
},
"minContains": 2, // At least 2 items must match contains
"maxContains": 5
}
Conditional Keywords (Draft 7+)
{
"type": "object",
"properties": {
"type": { "enum": ["personal", "business"] },
"company": { "type": "string" }
},
"if": {
"properties": { "type": { "const": "business" } }
},
"then": {
"required": ["company"] // company required only for business type
},
"else": {
"not": { "required": ["company"] }
}
}
Generating Schema from Sample JSON: How It Works Under the Hood
When you paste JSON into a schema generator, it performs a series of inference operations to produce the schema. Understanding this process helps you know what to expect and how to refine the output.
The Generation Algorithm (Simplified)
// Pseudocode of what a schema generator does:
function inferSchema(value: unknown): JSONSchema {
if (value === null) return { type: "null" };
const type = typeof value;
if (type === "boolean") return { type: "boolean" };
if (type === "number") {
return Number.isInteger(value)
? { type: "integer" }
: { type: "number" };
}
if (type === "string") {
const schema: JSONSchema = { type: "string" };
// Try to infer format
if (isEmail(value)) schema.format = "email";
else if (isUUID(value)) schema.format = "uuid";
else if (isISO8601(value)) schema.format = "date-time";
else if (isURL(value)) schema.format = "uri";
return schema;
}
if (Array.isArray(value)) {
if (value.length === 0) return { type: "array" };
// Merge schemas of all items to find common schema
const itemSchemas = value.map(inferSchema);
return {
type: "array",
items: mergeSchemas(itemSchemas)
};
}
if (type === "object") {
const properties: Record = {};
for (const [key, val] of Object.entries(value)) {
properties[key] = inferSchema(val);
}
return {
type: "object",
properties,
required: Object.keys(value) // All keys in sample = required
};
}
}
What the Generator Cannot Infer
A schema generator can only work with the data it's given. It cannot infer:
- Optional fields — Every key in your sample JSON will be marked as
required. You must manually remove optional fields fromrequired. - Value ranges — It won't add
minimum: 0to an age field. You add business rules manually. - String patterns — Unless you use a generator with format detection,
"SKU-123"won't becomepattern: "^SKU-\d+". - Nullable vs absent — The difference between a missing key and a
nullvalue must be modeled withanyOf: [{type: "X"}, {type: "null"}].
Merging Multiple Samples
// Sample 1: active user
{ "id": 1, "name": "Alice", "plan": "pro" }
// Sample 2: inactive user without plan
{ "id": 2, "name": "Bob" }
// After merging, generator produces:
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string" },
"plan": { "type": "string" } // appeared in only one sample
},
"required": ["id", "name"] // "plan" not in all samples → optional
}
Schema Validation: required, additionalProperties, enum and pattern
The real power of JSON Schema is expressing business rules as validation constraints. Here are the most impactful keywords in production schemas.
required — Mandatory Fields
{
"type": "object",
"properties": {
"id": { "type": "integer" },
"email": { "type": "string", "format": "email" },
"password": { "type": "string", "minLength": 8 },
"nickname": { "type": "string" } // optional
},
"required": ["id", "email", "password"] // nickname is optional
}
// VALID: { "id": 1, "email": "a@b.com", "password": "secret123" }
// INVALID: { "id": 1, "email": "a@b.com" }
// → "required property 'password' is missing"
additionalProperties — Strict Object Shape
// additionalProperties: false — reject unknown keys
{
"type": "object",
"properties": { "name": { "type": "string" } },
"additionalProperties": false
}
// INVALID: { "name": "Alice", "unknownField": 123 }
// additionalProperties: schema — allow but constrain extra keys
{
"type": "object",
"properties": { "id": { "type": "integer" } },
"additionalProperties": { "type": "string" }
}
// VALID: { "id": 1, "meta1": "foo", "meta2": "bar" }
// INVALID: { "id": 1, "meta1": 42 } ← extra value must be string
enum — Allowed Values
{
"type": "object",
"properties": {
"status": {
"type": "string",
"enum": ["pending", "active", "suspended", "deleted"]
},
"priority": {
"type": "integer",
"enum": [1, 2, 3, 4, 5]
},
"flag": {
"enum": [true, false, null] // enum can mix types
}
}
}
pattern — Regex Validation
{
"type": "object",
"properties": {
"username": {
"type": "string",
"pattern": "^[a-zA-Z0-9_]{3,30}$"
},
"phoneUS": {
"type": "string",
"pattern": "^\+1[2-9]\d{2}[2-9]\d{6}$"
},
"hexColor": {
"type": "string",
"pattern": "^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$"
},
"semver": {
"type": "string",
"pattern": "^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$"
},
"slug": {
"type": "string",
"pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$"
}
}
}
Combining Constraints with allOf / anyOf / oneOf
// Nullable string (can be string or null)
{
"anyOf": [
{ "type": "string", "minLength": 1 },
{ "type": "null" }
]
}
// Discriminated union (payment method)
{
"oneOf": [
{
"type": "object",
"properties": {
"type": { "const": "card" },
"cardNumber": { "type": "string", "pattern": "^\d{16}$" },
"expiryMonth": { "type": "integer", "minimum": 1, "maximum": 12 }
},
"required": ["type", "cardNumber", "expiryMonth"]
},
{
"type": "object",
"properties": {
"type": { "const": "paypal" },
"paypalEmail": { "type": "string", "format": "email" }
},
"required": ["type", "paypalEmail"]
}
]
}
JSON Schema in API Development: OpenAPI, Swagger and TypeScript
JSON Schema is the backbone of API description formats. Understanding the relationship between JSON Schema and OpenAPI/Swagger saves hours of confusion when building or consuming APIs.
OpenAPI 3.1 and JSON Schema
OpenAPI 3.1 (released 2021) aligned its Schema Object with JSON Schema Draft 2020-12 — meaning you can use any JSON Schema keyword directly in OpenAPI 3.1 schemas. OpenAPI 3.0 used a subset of JSON Schema Draft 4 with vendor extensions.
# OpenAPI 3.1 — full JSON Schema support
openapi: 3.1.0
info:
title: User API
version: 1.0.0
paths:
/users:
post:
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CreateUserRequest'
responses:
'201':
content:
application/json:
schema:
$ref: '#/components/schemas/User'
components:
schemas:
CreateUserRequest:
type: object
properties:
username:
type: string
minLength: 3
pattern: '^[a-zA-Z0-9_]+$'
email:
type: string
format: email
password:
type: string
minLength: 8
writeOnly: true # Only in requests, never in responses
required: [username, email, password]
additionalProperties: false
User:
type: object
properties:
id:
type: integer
readOnly: true # Only in responses, never in requests
username:
type: string
email:
type: string
format: email
createdAt:
type: string
format: date-time
readOnly: true
required: [id, username, email, createdAt]
TypeScript Code Generation from JSON Schema
# Generate TypeScript interfaces from JSON Schema
npm install -g json-schema-to-typescript
json2ts -i user.schema.json -o user.types.ts
// Generated user.types.ts:
export interface User {
id: number;
username: string;
email: string;
age?: number; // Optional: not in required[]
active: boolean;
roles: string[];
}
// With strict schemas, you get compile-time safety AND runtime validation
// from the same schema source of truth.
Runtime Validation with Ajv (Node.js)
import Ajv from 'ajv';
import addFormats from 'ajv-formats';
import userSchema from './user.schema.json';
const ajv = new Ajv({ allErrors: true });
addFormats(ajv); // Adds email, uri, date-time format validation
const validate = ajv.compile(userSchema);
function validateUser(data: unknown) {
const valid = validate(data);
if (!valid) {
console.error('Validation errors:', validate.errors);
// errors example:
// [{ instancePath: '/email', message: 'must match format "email"' },
// { instancePath: '', message: "must have required property 'username'" }]
return false;
}
return true;
}
// Usage:
validateUser({ id: 1, username: 'alice', email: 'not-an-email' });
// Logs: must match format "email"
Schema Reuse with $ref and $defs
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$defs": {
"Address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" },
"country": { "type": "string", "minLength": 2, "maxLength": 2 }
},
"required": ["street", "city", "country"]
},
"Email": {
"type": "string",
"format": "email"
}
},
"type": "object",
"properties": {
"billingAddress": { "$ref": "#/$defs/Address" },
"shippingAddress": { "$ref": "#/$defs/Address" },
"email": { "$ref": "#/$defs/Email" }
}
}
Common JSON Schema Mistakes and How to Fix Validation Errors
JSON Schema has several subtle behaviors that trip up developers. Here are the most common mistakes and their fixes.
Mistake 1: Forgetting that properties doesn't enforce presence
// WRONG — this schema does NOT require "name":
{
"type": "object",
"properties": {
"name": { "type": "string" }
}
}
// {} passes validation! properties only defines what the key LOOKS LIKE if present.
// CORRECT — use required:
{
"type": "object",
"properties": {
"name": { "type": "string" }
},
"required": ["name"]
}
Mistake 2: additionalProperties with allOf
// WRONG — additionalProperties doesn't see properties from $ref in Draft 4-7:
{
"allOf": [
{ "$ref": "#/$defs/Base" },
{
"type": "object",
"properties": { "extra": { "type": "string" } },
"additionalProperties": false // This ONLY sees "extra", not Base's properties!
}
]
}
// CORRECT — in Draft 2020-12, use unevaluatedProperties instead:
{
"allOf": [
{ "$ref": "#/$defs/Base" },
{
"type": "object",
"properties": { "extra": { "type": "string" } }
}
],
"unevaluatedProperties": false // Sees ALL properties from all subschemas
}
Mistake 3: integer vs number type
// JSON Schema "integer" type accepts ONLY whole numbers:
{ "type": "integer" }
// VALID: 42, -7, 0
// INVALID: 3.14, "42"
// JSON Schema "number" type accepts both integers and floats:
{ "type": "number" }
// VALID: 42, 3.14, -0.5
// INVALID: "42"
// Common mistake: using "number" for age fields (allows 25.7)
// Fix: use "integer" for whole-number fields
Mistake 4: Pattern escaping in JSON strings
// In JSON, backslash must be double-escaped:
{
"pattern": "^\d{3}-\d{4}$" // CORRECT: represents regex ^d{3}-d{4}$
}
{
"pattern": "^d{3}-d{4}$" // WRONG: JSON parse error — d is invalid JSON escape
}
Mistake 5: Null vs missing property
// These are DIFFERENT:
// Property absent: { "id": 1 } (missing key)
// Property null: { "id": 1, "bio": null } (key exists, value is null)
// To allow both absent AND null:
{
"properties": {
"bio": {
"anyOf": [
{ "type": "string" },
{ "type": "null" }
]
}
}
// "required" does NOT list "bio" — it can be absent
}
// In Draft 2020-12, shorthand:
{
"properties": {
"bio": { "type": ["string", "null"] } // type can be an array
}
}
Debugging Validation Errors with Ajv
import Ajv from 'ajv';
const ajv = new Ajv({ allErrors: true, verbose: true });
const schema = { /* your schema */ };
const validate = ajv.compile(schema);
const data = { /* your data */ };
validate(data);
if (validate.errors) {
validate.errors.forEach(err => {
console.log(`Path: ${err.instancePath || '(root)'}`);
console.log(`Message: ${err.message}`);
console.log(`Params:`, err.params);
console.log('---');
});
}
// Example output:
// Path: /email
// Message: must match format "email"
// Params: { format: 'email' }
// Path: (root)
// Message: must have required property 'username'
// Params: { missingProperty: 'username' }
JSON Schema vs TypeScript Interfaces vs Zod: When to Use What
All three tools describe data shapes but they solve different problems. Choosing wrong leads to duplication, runtime errors or brittle codebases.
Comparison Table
| Feature | JSON Schema | TypeScript Interface | Zod |
|---|---|---|---|
| Runtime validation | Yes (via Ajv, etc.) | No (erased at compile) | Yes (built-in) |
| Compile-time types | Via codegen only | Yes (native) | Yes (z.infer) |
| Language-agnostic | Yes | No (TS only) | No (JS/TS only) |
| OpenAPI integration | Native | Via decorators | Via zod-to-openapi |
| IDE autocomplete | For JSON/YAML files | Excellent | Excellent |
| Complex conditions | if/then/else, oneOf | Limited (discriminated unions) | z.discriminatedUnion, z.union |
| Bundle size | Ajv: ~30kb gzip | Zero (compile only) | ~8kb gzip |
| Error messages | Configurable | N/A | Excellent (z.ZodError) |
| Form generation | Yes (react-jsonschema-form) | No | Limited |
Decision Framework
Use JSON Schema when:
✓ Building language-agnostic APIs consumed by multiple clients
✓ Need to validate config files (VSCode, package.json schemata)
✓ OpenAPI/Swagger documentation is required
✓ Generating forms automatically from schema
✓ Validation happens outside TypeScript (Go, Python microservices)
Use TypeScript Interfaces when:
✓ Internal TypeScript-only codebase
✓ No runtime validation needed (trust your data sources)
✓ Simplest possible type annotation
✓ Performance-critical paths (zero runtime overhead)
Use Zod when:
✓ TypeScript fullstack app (Next.js, tRPC, Remix)
✓ Want types AND validation from single declaration
✓ Great error messages for form validation
✓ API boundary validation in Node.js with minimal setup
✓ Using tRPC (native Zod integration)
Zod to JSON Schema and Back
import { z } from 'zod';
import { zodToJsonSchema } from 'zod-to-json-schema';
// Define once with Zod:
const UserSchema = z.object({
id: z.number().int().positive(),
username: z.string().min(3).max(30).regex(/^[a-zA-Z0-9_]+$/),
email: z.string().email(),
age: z.number().int().min(0).max(150).optional(),
});
// Get TypeScript type:
type User = z.infer;
// Get JSON Schema (for OpenAPI docs):
const jsonSchema = zodToJsonSchema(UserSchema, { name: 'User' });
console.log(JSON.stringify(jsonSchema, null, 2));
// Get JSON Schema (Draft 7 for Ajv):
const jsonSchemaDraft7 = zodToJsonSchema(UserSchema, {
$refStrategy: 'none',
target: 'jsonSchema7',
});
How to Use the Tool (Step by Step)
- 1
Paste your sample JSON
Copy a real JSON object from your API response, config file or database record and paste it into the JSON Schema Generator input panel.
- 2
Select draft version
Choose the JSON Schema draft: Draft 2020-12 for new projects, Draft 7 for maximum tool compatibility, or Draft 4 for legacy systems. The generator adjusts keywords accordingly.
- 3
Configure generation options
Choose whether to mark all keys as required, detect string formats (email, URI, date-time, UUID), set additionalProperties to false, and whether to inline $defs or use $ref references.
- 4
Generate the schema
Click Generate. The tool infers types, detects formats, identifies nested structures and produces a complete, valid JSON Schema in under a second.
- 5
Review and refine
The generated schema is a starting point. Add business rules manually: remove keys from required[] that are optional, add minimum/maximum for numbers, tighten pattern constraints for strings.
- 6
Validate sample data
Use the inline validator to test your schema against multiple JSON examples. Catch validation errors before shipping your schema to production.
- 7
Copy and integrate
Copy the schema into your codebase, OpenAPI spec, Ajv validator setup, or CI/CD pipeline. The schema works with any JSON Schema-compliant validator.
Frequently Asked Questions
What is the difference between JSON Schema Draft 4, Draft 7 and Draft 2020-12?+−
Draft 4 (2013) established the foundation — type, properties, required, allOf/anyOf/oneOf. Draft 7 (2018) added if/then/else conditional validation, readOnly, writeOnly, $comment and improved $ref. Draft 2020-12 is the current standard: it added unevaluatedProperties (fixes the additionalProperties+allOf bug), prefixItems for typed arrays (tuples), $dynamicRef for recursive schemas, and fully aligned with JSON Schema core spec. For new projects, use Draft 2020-12. For maximum tooling compatibility, Draft 7 is a safe choice.
How does additionalProperties: false work with allOf and $ref?+−
In Draft 4 through Draft 7, additionalProperties only sees properties defined in the same schema object — it does NOT see properties from $ref or allOf siblings. This is a well-known footgun. The fix in Draft 2020-12 is to use unevaluatedProperties: false instead, which correctly considers all properties from all referenced schemas. In older drafts, the workaround is to repeat all property names in the object that has additionalProperties: false.
Can I generate TypeScript types from JSON Schema?+−
Yes — the json-schema-to-typescript package (json2ts CLI) generates TypeScript interfaces from any JSON Schema file. Run: npm install -g json-schema-to-typescript && json2ts -i schema.json -o types.ts. Alternatively, use Zod with zod-to-json-schema to maintain a single source of truth in TypeScript that produces both types and JSON Schema.
What is the best JSON Schema validator library for Node.js?+−
Ajv (Another JSON Validator) is the industry standard — it's the fastest, most spec-compliant and used by millions of packages. Install with: npm install ajv ajv-formats (for email, uri, date-time format validation). For browser environments, Ajv's bundle is about 30kb gzipped. Alternatives include ajv-8 (latest with Draft 2020-12 support by default) and hyperjump/json-schema-validator.
How do I validate an array where each item can be multiple types?+−
Use anyOf within items: { "type": "array", "items": { "anyOf": [{"type": "string"}, {"type": "integer"}] } }. For typed tuples (positional types), use prefixItems in Draft 2020-12: { "prefixItems": [{"type": "string"}, {"type": "integer"}], "items": false } — items: false means no additional items beyond what prefixItems defines.
Should I use JSON Schema or Zod for a Next.js API?+−
For a TypeScript-only Next.js project, Zod is simpler — you get types and runtime validation from one declaration with excellent error messages. If you also need to generate OpenAPI docs, add the zod-to-openapi or zod-openapi package to bridge both worlds. Use JSON Schema directly when you need language-agnostic validation, IDE schema support for config files, or when other non-TypeScript services consume your schemas.
Generate JSON Schema from Your JSON
Paste any JSON object and get a complete, valid JSON Schema instantly. Supports Draft 4, 7 and 2020-12. Free, no login required.
Open JSON Schema GeneratorRelated Guides
JSON Formatter Guide
A complete developer reference for JSON syntax, common errors, formatting options, and how to validate JSON in any language or tool.
How to Convert JSON to CSV — Free Online Guide (2026)
Convert JSON data to CSV format for Excel, databases, and data analysis — free, instant, browser-based.
Base64 Encode & Decode — What It Is, How It Works & When to Use It
Developer guide to Base64 encoding: use cases, online decoder, and common pitfalls