Frequently Asked Questions
Everything you need to know about DevKit tools — from JSON formatting to regex testing, with detailed troubleshooting for common developer issues.
General
Yes, all 21 tools are 100% free with no signup required. We support the site through display ads, never by charging for tools or selling your data.
Absolutely. All tools run entirely in your browser using client-side JavaScript. Your data is never uploaded to any server. Nothing leaves your device.
No. Just open any tool and start using it immediately. No email, no password, no verification step.
Once a tool page is loaded, it works offline since all processing happens client-side. You can bookmark tools for quick access.
All modern browsers including Chrome, Firefox, Safari, and Edge. The tools use standard web APIs that work everywhere.
Tools & Features
Our tools process data in the browser efficiently. For very large JSON files, formatting and validation work without freezing your tab. We are continuously improving performance for larger payloads.
Yes. The output generated by our tools is yours to use for any purpose — personal, commercial, or otherwise. There are no licensing restrictions on tool output.
Most tools support standard browser shortcuts (Ctrl+A to select all, Ctrl+C to copy, etc.). We are working on adding tool-specific keyboard shortcuts in the future.
Absolutely! Visit our tool request page and submit your idea. We prioritize tools with high search demand and user requests.
Not currently. Since all tools run client-side, you can inspect the JavaScript source to understand the algorithms. An API for programmatic access is on our roadmap.
Privacy & Security
No. We do not use Google Analytics, Hotjar, or any other analytics or tracking platform. We do not collect information about your browsing behavior, IP address, or device.
We use localStorage to remember your theme preference (dark/light mode). Google AdSense may set cookies for ad serving. See our Cookie Policy for details.
Yes. Since all processing happens in your browser, your data never leaves your device. We have no server-side endpoints. However, always exercise caution with sensitive data and verify you are on the correct website.
Monetization & Ads
No. All current tools will remain free forever. We may add premium features in the future (like an API or advanced tool), but the core tools will always be free.
Display ads keep DevKit free for everyone. We use Google AdSense with a $4-8 RPM in the developer/tech niche. Ads are clearly labeled and never interfere with tool functionality.
Yes, we may include affiliate links to developer tools and services (hosting, IDEs, etc.). These help support the site at no cost to you. Affiliate links do not affect tool output or recommendations.
JSON Formatter & Validator
The most common cause is a trailing comma. JSON does not allow trailing commas after the last element in an array or object. Other frequent causes include single quotes instead of double quotes, unquoted property keys, comments (JSON has no comments), and control characters like tabs inside strings. Our validator pinpoints the exact line and column of the error.
Yes. Our formatter recursively processes nested objects and arrays to any depth. However, for readability, we recommend keeping nesting under 5-6 levels. If your JSON is deeply nested due to API responses, consider flattening the structure or using JSON Path to access specific fields.
By default, the formatter preserves the original key order from your input. JSON objects are unordered by specification, but preserving insertion order makes diffs cleaner and is consistent with how most modern parsers (JavaScript, Python, Go) handle objects.
Formatting (pretty-printing) adds indentation, line breaks, and spaces for human readability. Minification removes all unnecessary whitespace to produce the smallest possible valid JSON, reducing file size by 20-40%. Use formatting during development and minification for production payloads.
The JSON specification (RFC 8259) states that objects SHOULD have unique keys but does not forbid duplicates. Our validator flags duplicate keys as warnings since most parsers silently keep only the last value, which can cause subtle data loss bugs.
Yes. The formatter handles Unicode characters correctly, including emoji, CJK characters, and escaped sequences like \u00e9. UTF-8 is the standard encoding for JSON, and all valid UTF-8 content is supported.
Our formatter processes data in the browser using efficient parsing. Files up to several megabytes format instantly. For files over 50MB, consider using our Large JSON Handler which uses streaming techniques to avoid freezing your browser tab.
Currently, the validator checks for syntactic correctness (valid JSON syntax) but does not validate against a JSON Schema. Schema validation compares your JSON against a defined structure (types, required fields, constraints) and is on our roadmap.
APIs may serialize JSON with different key orders, number formats (1 vs 1.0), or whitespace. This is normal — the data is semantically identical. Use a JSON Diff tool that compares parsed structures rather than raw text to avoid false positives.
JSON Minifier & Diff
Typically 20-40% for hand-written JSON with indentation and spaces. Heavily commented or verbose JSON can shrink by 50%+. However, if you serve JSON over HTTP with gzip compression enabled, the additional savings from minification are much smaller (5-10%) since gzip already compresses whitespace efficiently.
This is the most common JSON diff false positive. It happens when using text-based diff tools (like git diff) on JSON with reordered keys or different formatting. A structural JSON diff parses both inputs first and compares the data semantically, so key order and whitespace differences are ignored.
By default, array order matters in JSON — [1,2,3] and [3,2,1] are different. However, some arrays represent unordered sets (like tags or permissions). Our diff tool compares arrays element-by-element by index. If you need order-insensitive array comparison, sort both arrays before diffing.
Yes. The diff tool walks the entire JSON tree recursively and reports changes with full paths like user.address.city or items[2].price. This makes it easy to pinpoint exactly what changed, even in objects nested several levels deep.
No. Minified JSON parses to the exact same data structure as pretty-printed JSON. JSON.parse() ignores whitespace between tokens. Minification is purely a transport optimization — it reduces file size without changing the data.
The four most common are: (1) key reordering — objects are unordered in JSON but text diffs flag reordered keys as changes; (2) whitespace differences — minified vs pretty-printed JSON looks entirely different as text; (3) number representation — 1.0 vs 1 are equal but textually different; (4) array reordering when order does not matter semantically.
Yes. Paste the expected and actual API responses into the diff tool to see exactly what fields changed between deployments. This is especially useful for catching breaking changes in API contracts. For automated testing, consider using JSON Schema validation in your CI pipeline as well.
Yes. JSON minification only removes whitespace between tokens (outside of strings). Whitespace inside string values is always preserved. "hello world" stays "hello world" — only the spaces between keys, colons, and commas are removed.
A structural diff compares parsed JSON trees field-by-field — key order does not matter but value types and content must match exactly. A semantic diff goes further, understanding that 1.0 and 1 are the same number, or that two arrays contain the same elements in different orders. Our tool performs structural diffing by default.
Large JSON Handler
The tool handles files up to 50-100MB in the browser without freezing your tab. It uses Web Workers and chunked processing to keep the UI responsive. For files larger than 100MB, consider converting to NDJSON (newline-delimited JSON) or using server-side streaming parsers like stream-json (Node.js) or ijson (Python).
JSON.parse() loads the entire file into memory and builds a full object graph. A 100MB JSON file typically consumes 400-600MB of RAM due to object overhead, string representation, and container allocations. In Node.js, the default V8 heap limit is ~1.5GB, so files above ~200MB can cause out-of-memory crashes.
NDJSON (Newline-Delimited JSON) stores one JSON object per line instead of wrapping everything in a single array. This allows streaming parsers to process records one at a time with constant memory usage. A 1GB NDJSON file can be parsed with under 5MB of RAM, while a 1GB regular JSON file would require 4-5GB.
The tool uses Web Workers to move parsing off the main thread, preventing the UI from freezing. It also employs lazy tree expansion — only the visible nodes are rendered in the DOM, and deeper levels are parsed on demand when you expand them.
Yes. The tool indexes the JSON structure incrementally as it parses, allowing you to search for keys and values without fully materializing the object tree. Search results show the path to each match, so you can navigate directly to the relevant section.
For files over 500MB, use command-line tools: jq with --stream flag for filtering and extraction, stream-json in Node.js for programmatic processing, or ijson in Python. Consider converting to a binary format like Protocol Buffers or Parquet for production pipelines.
Yes. The Large JSON Handler detects whether your input is a single JSON document or NDJSON format. For NDJSON, each line is parsed independently, which is dramatically faster and uses less memory than parsing a single massive array.
Use JSONPath or jq-style expressions to extract only the fields you need. For example, $.users[*].email extracts all email addresses from a users array. This avoids loading the entire structure into memory and gives you just the data you need.
This occurs with deeply nested JSON structures (typically 100+ levels deep). The recursive descent parser exceeds the JavaScript engine's call stack limit. The Large JSON Handler uses iterative parsing for deeply nested structures to avoid this error.
JSON Converters (CSV, TypeScript, XML, YAML)
CSV is a flat format — rows and columns only. JSON supports nested objects and arrays that CSV cannot represent. When converting nested JSON to CSV, nested objects must be flattened into dotted column names (e.g., user.address.city) or dropped. Flat arrays of flat objects convert perfectly; deeply nested structures require decisions about how to flatten.
Yes. YAML 1.2 is a superset of JSON, so every JSON value has a direct YAML equivalent. The conversion is lossless in both directions. However, be aware of the "Norway problem" in YAML 1.1: unquoted values like NO, yes, on, and off are interpreted as booleans. Always quote ambiguous values.
XML has no native type system — numbers, booleans, and null all become text. 42 becomes <age>42</age> and true becomes <active>true</active>. The receiving system must know which fields are numeric or boolean. Array indices are also lost since XML uses repeated element names.
The tool inspects the shape of your JSON and generates TypeScript interface or type definitions. It infers types from values (string, number, boolean, null, array, object) and handles nested structures. The caveat: types reflect only the sample you provide, so use a representative example that includes optional and edge-case fields.
CSV has no type system — every cell is text. Most converters attempt type inference, converting "01234" to the number 1234, losing the leading zero. This is especially problematic for postal codes, phone numbers, and ID strings. Our converter preserves values as strings by default to prevent this.
Mixed-type arrays like [1, "hello", true] produce union types: (string | number | boolean)[]. The converter detects all unique types present in the array and generates the appropriate union. For arrays of objects with different shapes, it generates a union of interfaces.
JSON null has no direct XML equivalent. Common approaches include omitting the element entirely, using xsi:nil="true" (XML Schema), or using an empty element <field></field>. Our converter uses empty elements by default but can be configured to use xsi:nil for schema-aware consumers.
In YAML 1.1, unquoted two-letter country codes like NO are parsed as boolean false, and yes/on/off become true/false. YAML 1.2 fixed this, but many parsers (including PyYAML) still use 1.1 by default. Always quote ambiguous string values in YAML to prevent silent type coercion.
Yes. The converter uses the keys from the first object in the array as column headers. If objects have different keys, all unique keys across all objects are included. You can reorder or exclude columns before exporting. Objects with missing keys for a given column produce empty cells in the CSV output.
Base64 Encoder/Decoder
Base64 encodes binary data into ASCII text, making it safe to transmit over text-only channels like email, JSON APIs, and HTML. Common uses include embedding images in HTML/CSS (data URIs), encoding file attachments in email (MIME), transmitting binary data in JSON payloads, and storing binary data in text-based formats like YAML or XML.
No. Base64 is an encoding scheme, not encryption or compression. Anyone can decode Base64 without a key — it is reversible by design. The encoded output is approximately 33% larger than the input. Use encryption (AES, RSA) for confidentiality and compression (gzip, brotli) for size reduction.
Base64 encodes every 3 bytes of input into 4 characters of output. If the input length is not a multiple of 3, = padding characters are added to make the output length a multiple of 4. One = means 2 extra input bytes; two = means 1 extra input byte. The padding is required by the spec but some URL-safe variants omit it.
Standard Base64 uses + and / which have special meanings in URLs. URL-safe Base64 (base64url) replaces + with - and / with _, and optionally omits = padding. URL-safe Base64 is used in JWTs, data URIs, and other URL contexts.
Yes, but you must first convert the text to bytes using a character encoding (typically UTF-8). The sequence is: text → UTF-8 bytes → Base64 encode. When decoding: Base64 decode → UTF-8 bytes → text. If you skip the UTF-8 step and encode character codes directly, non-ASCII characters will produce incorrect output.
The most common cause is a character encoding mismatch. The original data was encoded with one charset (e.g., UTF-8) but decoded with another (e.g., Latin-1). Other causes include: the input was not valid Base64 (wrong padding, invalid characters), or the original data was binary (not text) and needs to be handled as a blob.
Absolutely not. Base64 is reversible encoding with no key — anyone who sees the encoded string can instantly decode it. For password storage, use a slow hashing algorithm like bcrypt, scrypt, or Argon2. For data confidentiality, use AES encryption. Base64 is for transport encoding, never for security.
There is no inherent size limit in the Base64 algorithm, but practical limits exist. URLs have length limits (~2000 characters in most browsers). JSON payloads with embedded Base64 can become very large. Our tool handles inputs up to several megabytes in the browser. For larger data, consider streaming or file-based approaches.
Different tools may use different Base64 variants (standard vs URL-safe), handle whitespace differently, or require/omit padding. Some tools accept newlines in Base64 input (MIME format wraps at 76 characters); others do not. Ensure you are using the same variant on both sides, and check for hidden whitespace or encoding issues.
URL Encode/Decode
encodeURI encodes a full URL but preserves characters that have special meaning in URLs (like :, /, ?, &, =). encodeURIComponent encodes everything except A-Z a-z 0-9 - _ . ! ~ * ' ( ), making it suitable for encoding individual query parameter values. Use encodeURIComponent for parameter values and encodeURI for full URLs.
Both are valid. %20 is the percent-encoded form of a space, used in URL paths and query strings. + is the application/x-www-form-urlencoded form, used specifically in HTML form submissions. In query strings, both %20 and + represent spaces. In URL paths, only %20 is valid.
URL-encode data when placing it in a URL (query parameters, path segments, fragment identifiers). HTML-encode data when placing it in HTML content or attributes (to prevent XSS). If data goes into both contexts (e.g., a URL inside an HTML attribute), HTML-encode the entire attribute value after URL-encoding the data within it.
Any character that is not A-Z a-z 0-9 - _ . ~ must be percent-encoded in a URL. This includes spaces, special characters like #, ?, &, =, /, and all non-ASCII characters. Reserved characters (:/?#[]@!$&'()*+,;=) have special meaning and should only be encoded when they appear as literal data, not as URL structure.
Different languages and libraries may use different encoding standards. JavaScript's encodeURIComponent does not encode !*'(), while Python's urllib.parse.quote does by default. Always check your library's documentation and specify the safe parameter or equivalent to control which characters are preserved.
Yes. Unicode characters are first converted to UTF-8 bytes, then each byte is percent-encoded. For example, the emoji 🚀 becomes %F0%9F%9A%80 (4 UTF-8 bytes, each encoded separately). This is the standard behavior defined by RFC 3986 and implemented by all modern browsers and libraries.
Double encoding happens when a value is URL-encoded twice. For example, %20 (an encoded space) gets encoded again to %2520. This occurs when a framework automatically encodes a value that was already encoded manually. Fix it by encoding only once at the boundary where the value enters the URL.
This usually means the input was encoded with a different character encoding than expected. URL encoding is defined for UTF-8, but some legacy systems use Latin-1 or other encodings. If %E9 decodes to é in UTF-8 but a different character in Latin-1, you have an encoding mismatch. Always use UTF-8 for URL encoding.
Yes, "URL encoding" and "percent encoding" are synonymous. Both refer to the process of replacing unsafe characters with a % followed by two hexadecimal digits representing the character's byte value. The term "percent encoding" is used in RFC 3986, while "URL encoding" is the more common informal name.
HTML Encoder
Five characters have special meaning in HTML and must be encoded when used as text content: & (&), < (<), > (>), " ("), and ' ('). In practice, encoding all five is always safe. The specific characters that must be encoded depend on context: text content vs attribute values vs single-quoted vs double-quoted attributes.
Double encoding occurs when already-encoded content is encoded again. < becomes <, which renders as the literal text < instead of <. This happens when content passes through multiple encoding layers (e.g., database → template engine → output filter). Encode once at the final output boundary, and decode once at the input boundary.
HTML entity encoding prevents XSS in HTML text content and attribute values, but it is not sufficient for all contexts. Inside <script> tags, JavaScript string escaping is needed. Inside event handlers (onclick), JavaScript encoding is needed. Inside CSS url(), CSS escaping is needed. Use context-aware encoding as described in the OWASP XSS Prevention Cheat Sheet.
Named entities use readable names: <, &, ". Numeric entities use Unicode code points: decimal (<) or hex (<). Both produce the same character. Named entities are more readable but only cover a limited set. Numeric entities can represent any Unicode character.
If you are displaying untrusted text as plain text in HTML, entity encoding is sufficient. If you need to allow some HTML (like bold, links) while blocking dangerous elements (<script>, event handlers), use a sanitization library like DOMPurify. Encoding converts HTML to visible text; sanitization filters HTML to a safe subset.
Unicode characters like emoji (🚀) do not need HTML encoding — they are valid in UTF-8 HTML documents. However, if you need to represent them as entities, use numeric entities: 🚀 (hex) or 🚀 (decimal). Modern browsers render Unicode characters directly without entity encoding when the document charset is UTF-8.
In HTML, the & character must be encoded as & even in URL attributes like href. A URL like ?a=1&b=2 in an HTML attribute should be written as ?a=1&b=2. The browser decodes the entity and sends the correct URL. This is not double encoding — it is the correct way to write URLs in HTML.
No. HTML entity encoding is for HTML contexts only. Inside <script> blocks, use JavaScript string escaping (\u003c for <). Inside JSON, use JSON string escaping (\u003c). Using HTML entities inside JavaScript or JSON will produce incorrect output since the browser does not decode HTML entities inside script blocks.
A correct HTML decoder returns unknown entity names unchanged — &widget; stays as &widget; rather than being dropped or replaced with a placeholder. This is important because unknown entities might be valid in a different context (like MathML or SVG) or might be custom entities defined in the document's DTD.
HTML & CSS Formatter
Inline elements like <span>, <a>, and <code> should not be placed on their own line, because whitespace between inline elements affects rendering (adds a space). A good HTML formatter preserves inline elements on the same line and only adds line breaks for block-level elements. Our formatter distinguishes between inline and block elements to avoid introducing rendering changes.
Yes. Void elements (<br>, <img>, <input>, <hr>, <meta>, <link>) never have closing tags or content. The formatter recognizes void elements and does not add closing tags, self-closing slashes, or content wrappers. This is a common bug in naive regex-based formatters.
Content inside <pre> and <code> elements is preserved exactly as-is — no re-indentation, no whitespace collapsing, no line breaking. This is critical because whitespace is significant in preformatted text. Re-indenting <pre> content would change the rendered output.
Aggressive CSS minification can break styles in several ways: merging selectors that rely on source order for specificity, shortening CSS custom property names (--my-color → --a) that are referenced in JavaScript, and removing trailing semicolons in nested rules. Our minifier preserves source order and does not rename custom properties.
CSS minification typically reduces file size by 20-30% by removing whitespace, comments, and unnecessary semicolons. Heavily commented files can shrink by 40-50%. However, if you serve CSS with gzip compression, the additional savings from minification are smaller (5-10%) since gzip already compresses whitespace efficiently.
Yes. The formatter supports modern CSS features including nested rules (& selector), @scope, @layer, and container queries. These are parsed correctly and indented based on their nesting level. Some older minifiers fail on these modern features, producing invalid CSS.
Beautify adds indentation, line breaks, and consistent spacing for human readability. Minify removes all unnecessary whitespace, comments, and optional tags to produce the smallest possible file. HTML minification typically reduces file size by 20-30%. Use beautify during development and minify for production.
The formatter recognizes <script> and <style> blocks and applies language-specific formatting: JavaScript formatting for scripts and CSS formatting for styles. Treating JavaScript or CSS as HTML markup would produce garbage output. The formatter preserves the content structure within these embedded blocks.
Some CSS formatters sort properties alphabetically or by category (layout, typography, colors). This can change cascade behavior if you rely on source order for overriding properties with the same specificity. Our formatter preserves the original property order by default, as reordering can introduce subtle bugs.
XML & YAML Formatter
XML allows both single and double quotes for attribute values. A formatter that walks the DOM and re-serializes must choose one quote style for the entire document, which may differ from the original. This is a serialization choice, not a content change. If you need byte-for-byte preservation, diff the original against the formatted output.
No. The formatter checks for well-formedness (valid XML syntax) but does not validate against an XML Schema Definition (XSD) or Document Type Definition (DTD). Well-formedness means tags are properly nested, attributes are quoted, and the document has a single root element. Schema validation checks that the structure matches a defined contract.
Mixed content elements (containing both text and child elements) require careful whitespace handling. The formatter categorizes elements as "ignore space", "normalize space", "mixed content", or "preserve space" based on their content. Elements with xml:space="preserve" are never reformatted. This prevents breaking documents where whitespace is significant.
Some YAML formatters have a default printWidth of 80 characters and automatically wrap lines that exceed it. This can break GitHub Actions expressions, CloudFormation templates, and CI configurations. You can disable line wrapping by setting a high print width or using the "never wrap" option. Our formatter preserves your original line structure.
Block scalars (| for literal, > for folded) preserve multiline strings. The formatter must not re-indent content inside block scalars because indentation is semantically meaningful. A common bug is formatters that re-indent block scalar content, breaking the string. Our formatter preserves block scalar content exactly.
Some YAML formatters interpret escaped newline characters (\n) in double-quoted strings and convert them to actual line breaks during formatting. This changes the semantic meaning — \n in a double-quoted string is a single newline character, while an actual line break in the YAML source creates a multiline string. This is a known issue with some VS Code YAML extensions.
Yes. The formatter preserves namespace declarations (xmlns:prefix), namespace-qualified elements and attributes, and CDATA sections. Comments are preserved by default. However, processing instructions and DOCTYPE declarations may be normalized. If you need strict preservation of all XML features, compare the output with the input.
YAML is one of the few config formats that supports comments (#). Our formatter preserves comments in their original positions. However, comments inside arrays may be repositioned by some formatters because the YAML data model does not have a canonical way to associate comments with specific array items.
XML minify removes whitespace, comments, and unnecessary closing tags to produce the smallest valid XML. XML format (beautify) adds indentation and line breaks for readability. Minify is used for production transmission; format is used during development. Both share the same parser but produce different output. Comments are preserved by default in both modes.
Regex Tester
Regex engines differ across languages. JavaScript uses a PCRE-like engine but lacks lookbehind support in older versions. Python has different syntax for some constructs. Java requires double-escaping in strings. POSIX regex (grep) has a much smaller feature set. Always test your regex in the target language. Our tester uses the JavaScript regex engine, which covers most common use cases.
Greedy quantifiers (*, +, ?, {n,m}) match as much as possible, then backtrack. Lazy quantifiers (*?, +?, ??, {n,m}?) match as little as possible. For example, .* on "hello world" matches the entire string, while .*? matches nothing (empty string). Use lazy quantifiers when you want the shortest match.
Escape special characters with a backslash: \. matches a literal dot, \* matches a literal asterisk, \+ matches a literal plus. The special characters that need escaping are: . * + ? ^ $ { } [ ] \ | ( ). Inside character classes [...], only \ ] ^ - need escaping.
Lookahead (?=...) checks that what follows matches without consuming it. Negative lookahead (?!...) checks that what follows does NOT match. Lookbehind (?<=...) checks what precedes. Negative lookbehind (?<!...) checks that what precedes does NOT match. These are zero-width assertions — they do not consume characters. JavaScript supports lookbehind since ES2018.
Word boundaries \b match between a word character ([A-Za-z0-9_]) and a non-word character. They do not work correctly with Unicode characters or non-ASCII text. For Unicode word boundaries, use \p{L} with the u flag in modern JavaScript. Also, \b does not match at the start of a string if the first character is a non-word character.
The g flag finds all matches (not just the first). The i flag makes matching case-insensitive. The m flag makes ^ and $ match at line boundaries (not just string boundaries). The s flag (dotAll) makes . match newlines. The u flag enables Unicode mode for proper handling of astral characters. Combine flags like /pattern/gim.
Parentheses (...) create capturing groups. You can reference them with backreferences: \1 for the first group, \2 for the second. Use (?:...) for non-capturing groups when you need grouping without capturing. Named groups (?<name>...) are supported in modern JavaScript and are more readable than numbered groups.
Catastrophic backtracking occurs with nested quantifiers like (a+)+ or (a|a)*b on certain inputs. The regex engine tries an exponential number of combinations before failing. This can freeze your application. Fix it by using possessive quantifiers (not in JS), atomic groups (not in JS), or restructuring the regex to avoid ambiguous alternatives. Test with long inputs to detect this issue.
No. HTML and JSON are recursive structures that cannot be parsed by regular expressions (which describe regular languages). Use a proper parser: DOMParser for HTML, JSON.parse for JSON. Regex can extract specific patterns from HTML/JSON for quick tasks, but it will fail on nested structures, edge cases, and malformed input. This is one of the most common regex anti-patterns.
JWT Decoder
A JWT (JSON Web Token) has three Base64URL-encoded parts separated by dots: header.payload.signature. The header specifies the algorithm (e.g., HS256, RS256). The payload contains claims (user ID, expiration, roles). The signature is computed over the header and payload using the specified algorithm and a secret key. Our decoder shows all three parts in decoded JSON.
No. Decoding a JWT simply Base64URL-decodes the header and payload — it does not verify the signature. Anyone can decode a JWT without the secret key. Signature verification requires the secret (for HMAC algorithms) or public key (for RSA/ECDSA). Decoding is for inspection; verification is for trust. Never accept a JWT based on decoding alone.
Standard claims defined by RFC 7519 include: iss (issuer), sub (subject), aud (audience), exp (expiration time), nbf (not before), iat (issued at), and jti (unique JWT ID). The exp claim is a NumericDate (seconds since epoch, not milliseconds). Custom claims can be added alongside standard ones.
JWT uses NumericDate for time claims — seconds since the Unix epoch (1970-01-01). JavaScript's Date expects milliseconds. If you pass a JWT exp value directly to new Date(), you get a date in 1970. Multiply by 1000: new Date(exp * 1000). Our decoder handles this conversion automatically.
HS256 (HMAC-SHA256) uses a single shared secret for both signing and verification — both parties must know the secret. RS256 (RSA-SHA256) uses a private key to sign and a public key to verify — the verifier only needs the public key. RS256 is preferred for distributed systems where the verifier should not have signing capability. Other algorithms include ES256 (ECDSA) and PS256 (RSA-PSS).
Yes, but that is a JWE (JSON Web Encryption), not a standard JWT (JWS). A standard JWT is signed but not encrypted — the payload is Base64URL-encoded and readable by anyone. JWE encrypts the payload so only holders of the decryption key can read it. Our tool decodes standard JWS tokens. If your token has 5 parts instead of 3, it may be a JWE.
No. The JWT payload is Base64URL-encoded, not encrypted. Anyone who intercepts the token can decode and read the payload. Never store passwords, API keys, credit card numbers, or other sensitive data in a JWT. Store only identifiers (user ID, roles) and use the token as an authentication reference, not a data container.
When the exp claim time is passed, the token should be rejected by the server. The client must obtain a new token, typically using a refresh token. JWTs are stateless — the server does not track them, so there is no way to "revoke" a JWT before expiration without additional infrastructure (like a blacklist). Keep expiration times short (15-60 minutes) and use refresh tokens for longer sessions.
JWTs are often used in URLs (query parameters, cookies), so they use Base64URL encoding which replaces + with - and / with _, and omits = padding. This avoids URL encoding issues. When decoding a JWT, convert Base64URL to standard Base64 (replace characters and add padding) before using standard Base64 decoders.
UUID Generator
A UUID (Universally Unique Identifier) is a 128-bit identifier represented as 32 hex digits in 5 groups separated by hyphens: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. The structure includes a version number (bits 48-51) and a variant number (bits 64-65). UUIDs are designed to be unique across space and time without central coordination.
UUID v1 is time-based — it uses the current timestamp and the machine's MAC address, making it sortable by creation time but potentially leaking the machine's identity. UUID v4 is random — it uses cryptographically secure random numbers for all bits except version and variant, making it non-sortable but privacy-preserving. UUID v4 is the most commonly used version.
No. UUID v4 has 122 bits of randomness, giving 2^122 ≈ 5.3 × 10^36 possible values. The probability of a collision among 103 trillion UUIDs is 50%. At a rate of generating 1 billion UUIDs per second, it would take 85 years to have a 50% chance of a single collision. For practical applications, collisions are effectively impossible.
Yes, but with trade-offs. UUIDs provide global uniqueness (useful for distributed systems, offline-first apps, and sharding) but are larger than integer keys (16 bytes vs 4-8 bytes), which increases index size and reduces cache efficiency. UUID v7 (time-ordered) is a better choice for database keys because it is sortable, improving index locality compared to random v4 UUIDs.
UUID v7 (RFC 9562) combines a Unix timestamp with random bits, producing time-ordered UUIDs that are sortable — ideal for database primary keys. UUID v8 is a custom version that allows application-specific data in the UUID structure. Both are newer than v4 and address the non-sortability problem of random UUIDs.
Store as binary (16 bytes / BINARY(16) in MySQL, UUID in PostgreSQL) for efficiency. The string representation is 36 characters (288 bits vs 128 bits), which wastes storage and slows index lookups. Most databases have native UUID types or functions: PostgreSQL uuid type, MySQL BINARY(16), MongoDB ObjectId or UUID.
UUID v1 uses the machine's MAC address and current timestamp. If you generate multiple v1 UUIDs on the same machine in quick succession, they share the same node (MAC) bits and have similar timestamp prefixes. This is expected behavior. Use UUID v4 if you want completely random identifiers with no correlation.
UUID v4 can be used as a non-secret identifier (e.g., a session ID stored in a cookie), but it should not be used as a security token or password. UUID v4 uses a CSPRNG (Cryptographically Secure Pseudo-Random Number Generator) in compliant implementations, but not all implementations are compliant. For security tokens, use a dedicated library that generates cryptographically secure random bytes.
Use UUID v7, which embeds a Unix millisecond timestamp in the first 48 bits, making UUIDs naturally sortable by creation time. This is particularly useful for database indexes, event logs, and time-series data. Alternatively, use ULID (Universally Unique Lexicographically Sortable Identifier) which has a similar design with a 48-bit timestamp and 80 bits of randomness.
Cron Expression Generator
A cron expression has 5 fields: minute hour day-of-month month day-of-week. Each field specifies when a task runs. For example, 0 9 * * 1-5 means 9:00 AM on weekdays. Some systems add a sixth field for seconds at the beginning. Our generator helps you build cron expressions visually without memorizing the syntax.
0 0 * * * runs at midnight every day. 0 0 1 * * runs at midnight on the 1st of every month. The * means "every value" for that field. In the day-of-month field, * means every day, while 1 means only the 1st. Understanding which fields are * vs specific values is key to reading cron expressions.
Use */15 * * * *. The */15 in the minute field means "every 15 minutes starting from 0" — it runs at :00, :15, :30, and :45. Note that */15 does NOT mean "15 minutes after the previous run" — it means "when the minute is divisible by 15." For intervals that do not divide 60 evenly (like every 7 minutes), use a different approach.
During DST fall-back (November in the US), clocks go back one hour. The period 1:00 AM to 1:59 AM occurs twice. A cron job scheduled at 1:30 AM fires during both occurrences. Conversely, during spring-forward (March), 2:00 AM to 2:59 AM does not exist, so a job at 2:30 AM does not run. Run cron jobs in UTC to avoid DST issues.
Linux cron has 5 fields (minute hour day month weekday). Spring/Quartz adds a seconds field (6 fields) and a year field (7 fields, optional). The day-of-week and day-of-month fields also differ: in Linux cron, specifying both means OR (runs if either matches); in Spring/Quartz, both must match. Always check your scheduler's documentation.
Use 0 0 L * * in schedulers that support the L modifier (Quartz, Spring). Standard Linux cron does not support L — you need a workaround: 0 0 28-31 * * with a check inside the script for the last day. Alternatively, use 0 0 1 * * to run on the 1st of the next month instead.
Standard cron does not support sub-minute intervals — the minimum is 1 minute. Some extended cron implementations (like Quartz) support seconds, but not sub-second. For sub-minute scheduling, use a different mechanism: a loop with sleep, a timer in your application code, or a message queue with delayed delivery.
*/5 means "every 5th value starting from the minimum." In the minute field, it runs at 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55. It does NOT mean "5 minutes after the last run." This distinction matters for intervals that do not evenly divide the field range. For example, */7 in minutes runs at 0, 7, 14, 21, 28, 35, 42, 49, 56 — then jumps to 0 (not 63).
Use our Cron Expression Generator to see the next N execution times for your expression. This helps verify the schedule matches your intent before deploying to production. Common mistakes include confusing day-of-month with day-of-week, or forgetting that specifying both creates an OR condition in standard cron.
Bcrypt & Hash Generator
Bcrypt is a password hashing function designed to be slow — it includes a work factor (cost) that increases the computation time exponentially. This makes brute-force attacks impractical. SHA-256 is a fast hash designed for data integrity, not password storage — a GPU can compute billions of SHA-256 hashes per second but only thousands of bcrypt hashes. Always use bcrypt (or scrypt/Argon2) for password storage.
The cost factor (also called rounds) determines how many iterations bcrypt performs — 2^cost iterations. A cost of 10 means 1,024 iterations; cost 12 means 4,096. Higher cost = more secure but slower. Aim for ~250ms per hash on your production hardware. Start at 10-12 and increase over time as hardware improves. Never go below 10.
Bcrypt includes a random salt in every hash, so the same password produces different hashes each time. This is by design — it prevents rainbow table attacks. To verify a password, use bcrypt's compare function, which extracts the salt from the stored hash and re-hashes the input with that salt. Never compare bcrypt hashes with ===.
No. MD5 and SHA-256 are general-purpose hash functions designed for speed. A modern GPU can compute billions of MD5/SHA-256 hashes per second, making them vulnerable to brute-force and rainbow table attacks. Use bcrypt, scrypt, or Argon2 — these are specifically designed for password hashing with built-in salting and adjustable work factors.
The most common cause is character encoding. SHA-256 hashes bytes, not characters. If Python uses encode('utf-8') but JavaScript uses a different encoding, the byte sequences differ. Other causes: trailing whitespace or newlines in one input but not the other, or line ending differences (LF vs CRLF). Always specify UTF-8 explicitly and check for hidden whitespace.
Hashing is one-way — you cannot recover the original input from the hash. Encryption is two-way — you can decrypt the ciphertext back to plaintext using a key. Use hashing for passwords and data integrity verification. Use encryption for data that needs to be recovered (credit card numbers, messages). Hashing is for verification; encryption is for confidentiality.
Use the bcrypt compare function: bcrypt.compare(userInput, storedHash). This extracts the salt and cost from the stored hash, re-hashes the user input with those parameters, and compares the result. Never extract the salt manually or compare hashes with string equality. The compare function handles timing-safe comparison to prevent timing attacks.
The Hash Generator supports MD5, SHA-1, SHA-256, SHA-384, SHA-512, and SHA-3. These are general-purpose cryptographic hash functions for data integrity, checksums, and file verification. For password storage, use the dedicated Bcrypt Generator instead, as general-purpose hashes are too fast for password security.
No. SHA-1 has been cryptographically broken — practical collision attacks exist (demonstrated by Google's SHAttered attack in 2017). Collisions mean two different inputs can produce the same hash, breaking integrity guarantees. Migrate to SHA-256 or SHA-3. MD5 is even weaker and should never be used for security purposes. MD5 is still acceptable for non-security checksums (like file deduplication).
Timestamp Converter
You are passing Unix seconds to a function that expects milliseconds. JavaScript's Date always works in milliseconds. If you pass 1712700000 (seconds) to new Date(), it interprets it as ~20 days after January 1, 1970. Multiply by 1000: new Date(1712700000 * 1000). Rule of thumb: 10-digit timestamp = seconds, 13-digit = milliseconds.
For seconds to milliseconds: multiply by 1000. For milliseconds to seconds: divide by 1000 and floor the result. In JavaScript: Math.floor(Date.now() / 1000) gives seconds. In Python: int(time.time()) gives seconds, int(time.time() * 1000) gives milliseconds. Always document which unit your API uses — epoch_s or epoch_ms in field names prevents confusion.
On January 19, 2038, a signed 32-bit Unix timestamp overflows from 2,147,483,647 to -2,147,483,648 (year 1901). This affects MySQL TIMESTAMP columns (pre-8.0.28), 32-bit embedded systems, and legacy C code. Most modern 64-bit systems are unaffected. If your application handles dates beyond 2038 (long-term contracts, mortgages), use DATETIME instead of TIMESTAMP in MySQL and ensure 64-bit time types.
The same Unix timestamp represents the same instant, but displaying it in local time depends on the machine's timezone. toLocaleString() uses the runtime's local timezone. A server in UTC and a laptop in New York show different local times for the same timestamp. Always use toISOString() for UTC output, or specify the timezone explicitly: Intl.DateTimeFormat('en-US', {timeZone: 'America/New_York'}).
A Unix timestamp is a single number (seconds or milliseconds since epoch). ISO 8601 is a string format like 2026-01-15T14:30:00Z that includes date, time, and timezone information. Unix timestamps are timezone-independent (always UTC). ISO 8601 can include timezone offsets (+05:30) or use Z for UTC. Both represent the same instant when the timezone is accounted for.
Unix timestamps are in UTC and are not affected by DST. However, converting a local date-time to a timestamp during DST transitions is ambiguous: during fall-back, 1:30 AM occurs twice (which one do you mean?), and during spring-forward, 2:30 AM does not exist. Use a timezone-aware library and specify the timezone explicitly to handle these edge cases correctly.
Some databases (PostgreSQL, ClickHouse) and tracing systems (OpenTelemetry, Jaeger) use microsecond (6 decimal places) or nanosecond (9 decimal places) precision. A microsecond timestamp has 16 digits; a nanosecond timestamp has 19 digits. Convert to milliseconds by dividing by 1000 (microseconds) or 1,000,000 (nanoseconds). JavaScript Date only supports millisecond precision.
JavaScript's Number type is a 64-bit floating point, which can only represent integers exactly up to 2^53 (9,007,199,254,740,992). Some API timestamps (like Discord snowflake IDs) exceed this limit, causing silent precision loss. Use BigInt for 64-bit integer timestamps, or store them as strings. Our converter handles both Number and BigInt inputs.
Use Intl.DateTimeFormat with the timeZone option: new Intl.DateTimeFormat('en-US', {timeZone: 'America/New_York', dateStyle: 'full', timeStyle: 'short'}).format(new Date(timestamp * 1000)). For server-side, use a library like luxon, date-fns-tz, or Python's zoneinfo. Always use IANA timezone names (e.g., America/New_York), not abbreviations like EST/EDT.
Number Base Converter
Binary (base 2) for bitwise operations and flags. Octal (base 8) for Unix file permissions (chmod). Decimal (base 10) for everyday use. Hexadecimal (base 16) for memory addresses, color codes, UUIDs, and byte representation. Base36 is used for URL shorteners. Our converter supports bases 2 through 36 and handles arbitrarily large numbers using BigInt.
JavaScript's Number type is a 64-bit float, which can only represent integers exactly up to 2^53. Hex numbers larger than 0x20000000000000 lose precision when converted to Number. Use BigInt for large hex values: BigInt('0xFFFFFFFFFFFFFFFF'). Our converter uses BigInt internally to handle arbitrarily large numbers without precision loss.
Each hex digit maps to exactly 4 binary digits (nibble). Hex F = binary 1111, hex A = binary 1010. To convert hex to binary, replace each hex digit with its 4-bit equivalent. To convert binary to hex, group bits into nibbles from the right and convert each group. This 1:4 ratio makes hex a compact representation of binary.
0x prefix denotes hexadecimal (e.g., 0xFF). 0b prefix denotes binary (e.g., 0b1010). 0o prefix denotes octal (e.g., 0o755). In older JavaScript, a leading 0 without o was octal (legacy, deprecated). No prefix means decimal. Our converter recognizes all standard prefixes automatically.
A hex color like #FF5733 has three 2-digit hex values: FF (red) = 255, 57 (green) = 87, 33 (blue) = 51. Each pair represents one byte (0-255). Convert each pair from hex to decimal. Shorthand notation like #F53 expands to #FF5533 by duplicating each digit.
In older JavaScript (pre-ES5), parseInt treated strings starting with 0 as octal. "08" is invalid octal (8 is not an octal digit), so it returned 0. ES5 changed this — parseInt("08") now returns 8. Always pass the radix: parseInt("08", 10) to avoid this legacy behavior. Our converter always specifies the base explicitly.
Base36 uses digits 0-9 and letters A-Z (case-insensitive). It is used in URL shorteners, YouTube video IDs, and Reddit link IDs because it is compact and URL-safe. A base36 number is roughly 60% shorter than its decimal equivalent. Our converter supports base36 alongside all bases from 2 to 36.
Unix permissions use 3 octal digits, each representing read (4), write (2), and execute (1) for owner, group, and others. 755 = owner rwx (7), group r-x (5), others r-x (5). 644 = owner rw- (6), group r-- (4), others r-- (4). Each octal digit maps to 3 binary bits representing the permission flags.
Our converter focuses on integer conversion, which is the most common use case. Floating-point conversion between bases is more complex because fractional parts may not have exact representations in the target base (e.g., 0.1 decimal is a repeating fraction in binary). For floating-point analysis, use a dedicated IEEE 754 converter.
SQL Formatter
Most SQL formatters default to a generic SQL dialect. PostgreSQL-specific operators like ::jsonb casts, RETURNING clauses, and ~ regex operators may not be recognized. Always select the correct SQL dialect (PostgreSQL, MySQL, SQLite, SQL Server, BigQuery) before formatting. Using the wrong dialect can produce syntactically valid but semantically incorrect SQL.
There is no single standard. Uppercasing keywords (SELECT, FROM, WHERE) is a convention from the era before syntax highlighting — it visually separated keywords from identifiers. Modern editors color-code keywords, so lowercase is equally readable. The key is consistency: pick one convention and apply it across your codebase. Our formatter supports both.
Leading commas (at the start of the next line) produce cleaner git diffs — adding a column only touches one line. Trailing commas (at the end of the line) are more conventional and readable for most developers. Our formatter uses trailing commas by default but can be configured for leading commas. The choice is stylistic, not functional.
Both single-line (--) and multi-line (/* */) comments are preserved during formatting. Comments are kept on their original line when possible. Inline comments on the same line as SQL code are preserved. However, leading commas combined with inline comments can cause formatting issues in some tools — use trailing commas if you rely heavily on inline comments.
Basic formatting of stored procedures and functions is supported, but complex PL/pgSQL, T-SQL, or PL/SQL blocks with control flow (IF, WHILE, cursors) may not be perfectly formatted. These procedural extensions have dialect-specific syntax that general SQL formatters do not fully parse. For complex stored procedures, use a dialect-specific formatter.
Standard indentation puts each major clause (SELECT, FROM, WHERE, GROUP BY, ORDER BY) on its own line, with subqueries indented one level. Two-space indentation is common and fits more nesting on screen. Four-space indentation makes nesting more visually obvious. Pick one and apply it consistently across your codebase.
Most SQL formatters do not understand templating syntax and may break on {{ variable }} or {% if %} blocks. The workaround is to format the SQL before injecting template variables, or use a formatter that supports templating (like sqlfmt with Jinja support). Our formatter does its best to preserve templating syntax without breaking it.
SQL has no single dominant style guide (unlike Python's PEP 8). Different formatters make different choices for keyword casing, comma placement, indentation depth, and line wrapping. Agree on a formatter and configuration within your team, and apply it via CI/CD to ensure consistent output. Our formatter uses sensible defaults but can be customized.
Yes. The formatter supports BigQuery-specific functions like SAFE_DIVIDE, Snowflake's QUALIFY clause, and other dialect-specific syntax. Select the appropriate dialect before formatting. Using the wrong dialect can silently strip unknown clauses or misformat functions, producing SQL that runs but returns wrong results.
JavaScript Minifier
Basic minification (whitespace and comment removal) reduces file size by 30-50%. Advanced minification with variable renaming (mangling), dead code elimination, and expression simplification can reduce size by 50-70%. However, with gzip compression enabled, the additional savings from advanced minification are smaller (10-20%) since gzip already compresses whitespace and repeated patterns.
Yes, in edge cases. Code using eval() or new Function() with variable names that get mangled will break. Code relying on Function.prototype.name for debugging will lose function names. ASI (Automatic Semicolon Insertion) edge cases can cause issues when newlines are removed. Always test the minified output. Use keep_fnames and reserved options to protect specific variables.
Minification reduces file size by removing whitespace, comments, and shortening variable names — the code still works the same. Obfuscation deliberately makes code hard to reverse-engineer by renaming everything to cryptic names, inserting dead code, and encoding strings. Obfuscation often makes code larger. Minification is for performance; obfuscation is for (weak) intellectual property protection.
Minification changes variable names, line numbers, and removes whitespace, making stack traces point to meaningless locations. Generate source maps (.map files) alongside minified code. Browsers and error tracking tools (Sentry, Bugsnag) use source maps to translate minified stack traces back to original source locations.
Minify after bundling (combining all modules into one file). Bundling first allows the minifier to perform cross-module optimizations like dead code elimination and function inlining. Minifying individual files before bundling prevents these optimizations. Modern build tools (Vite, Webpack, esbuild) handle bundling and minification together automatically.
You can beautify (add whitespace and indentation back), but you cannot recover original variable names. Once a minifier renames calculateTotalPrice to a, the original name is gone. Source maps can recover names if they were generated during minification. Without source maps, beautified minified code is readable but uses single-letter variable names.
Tree shaking (dead code elimination) removes unused exports from ES modules. If you import a utility library but only use one function, tree shaking removes the rest. This is done by bundlers (Webpack, Vite, Rollup), not minifiers. Tree shaking reduces bundle size dramatically; minification then compresses what remains. Both are needed for optimal production builds.
Minification improves load time (smaller file downloads faster) but does not significantly affect execution speed. The JavaScript engine compiles the code regardless of variable name length. In some cases, minified code can be slightly faster due to reduced parsing time, but the difference is negligible compared to the download speed improvement.
Use a well-tested minifier like Terser (the standard for Webpack/Vite). Generate source maps. Run your test suite against the minified build. Check the browser console for errors. Set up CI/CD checks to catch minification issues. Keep the unminified source as the canonical version — never edit minified code directly.
Markdown to HTML
Our converter supports GitHub Flavored Markdown (GFM), which extends CommonMark with tables, task lists, strikethrough (~~text~~), and autolinks for bare URLs. GFM is the de facto standard for developer documentation — it is what GitHub renders in READMEs, issues, and comments. CommonMark alone does not support tables or task lists.
Yes. Markdown allows raw HTML by specification, which creates XSS vulnerabilities when processing untrusted input. Our converter sanitizes the output by default, stripping dangerous elements (<script>, event handlers like onclick) while preserving safe formatting tags. For user-generated content, always use a sanitizer like DOMPurify on the HTML output.
Different Markdown parsers handle edge cases differently. CommonMark resolved most ambiguities, but extensions (tables, task lists, math) vary by parser. GitHub uses GFM with its own extensions. Your blog may use a different parser (markdown-it, marked, remark). For consistent rendering, use a GFM-compliant parser and test with the same tool you deploy.
Yes, but the conversion is lossy. HTML has features Markdown cannot represent: inline styles, classes, IDs, colspan/rowspan in tables, <div> layouts, and target="_blank" on links. Libraries like Turndown get you ~80% of the way. Expect manual cleanup after automated HTML-to-Markdown conversion.
Fenced code blocks (```language) are converted to <pre><code class="language-..."> elements. Syntax highlighting is applied client-side using a highlighter like Prism.js or highlight.js. The converter adds the appropriate CSS class; the highlighter handles the coloring. Without a highlighter, code blocks render as plain monospaced text.
In standard Markdown, a single newline is treated as a space (soft break). To force a line break (<br>), end the line with two spaces or a backslash (\). GFM also supports hard breaks with a newline in some contexts. If your content has significant line breaks, check that they have the trailing two spaces or use fenced code blocks.
Yes. GFM tables use pipe syntax (| Column | Column | with alignment via :---:). Task lists use - [x] for checked and - [ ] for unchecked items. Both are supported in our converter. Standard CommonMark does not support these — they are GFM extensions.
LaTeX math ($E = mc^2$) is not part of CommonMark or GFM. It requires a renderer extension like KaTeX or MathJax. GitHub supports it in some contexts. Our converter does not render math by default — it passes through the LaTeX syntax. Add KaTeX or MathJax to your page to render math equations.
Standard Markdown only supports  for images, which does not support captions, width, or height. For richer images, use raw HTML: <figure><img src="url" alt="alt"><figcaption>Caption</figcaption></figure>. Some Markdown extensions add image attributes, but they are not part of the standard.
HTTP Status Codes
401 means the client has not authenticated — "I do not know who you are." The response should include a WWW-Authenticate header. 403 means the client is authenticated but lacks permission — "I know who you are, and you cannot do this." Returning 403 for an unauthenticated request is wrong; returning 401 for an authenticated but unauthorized request is also wrong.
Use 301 Moved Permanently for permanent URL changes — search engines update their index and pass link equity. Use 302 Found for temporary redirects — the original URL remains canonical. Note: both 301 and 302 may downgrade POST to GET in browsers. Use 307 (temporary) or 308 (permanent) to preserve the HTTP method.
400 means the request is syntactically invalid — malformed JSON, missing required fields, wrong content type. 422 means the request is syntactically valid but semantically invalid — the JSON is well-formed but fails business rule validation (e.g., email format is valid but the domain does not exist). Use 422 for validation errors in APIs.
Without Retry-After, the client does not know how long to wait before retrying. It will either retry immediately (hammering your rate limiter) or give up entirely. Retry-After tells the client exactly when to retry. Also include X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset headers so clients can avoid hitting the limit.
502 Bad Gateway — a proxy/gateway received an invalid response from the upstream server (the upstream crashed or returned garbage). 503 Service Unavailable — the server is temporarily unable to handle the request (overloaded, maintenance). 504 Gateway Timeout — the proxy did not receive a response from the upstream server within the timeout period. 502 and 504 indicate the problem is upstream; 503 indicates the server itself is the problem.
Always return the correct HTTP status code. Returning 200 OK with {"success": false} breaks HTTP semantics — monitoring tools, API gateways, and client libraries that rely on status codes will classify the request as successful. Use 4xx for client errors, 5xx for server errors, and 2xx only for actual success.
Use 404 Not Found when a resource does not exist or you want to hide its existence for security reasons. Use 410 Gone when the resource existed but was permanently removed — this tells clients and search crawlers to stop requesting it and update their links. 410 is semantically stronger than 404 for deleted content.
Per RFC 9111: 200, 203, 204, 206, 300, 301, 404, 405, 410, 414, and 501 are cacheable by default. 302 and 307 are cacheable if explicitly allowed. 400, 403, 404 can be cached with explicit Cache-Control headers. 500, 502, 503, 504 should NOT be cached by default. Always set explicit Cache-Control headers rather than relying on defaults.
For security-sensitive endpoints, return 404 instead of 403. If you return 403, you reveal that the resource exists but the user lacks permission — an attacker can enumerate endpoints. Returning 404 reveals nothing about the resource's existence. This is a judgment call: 403 is more helpful for debugging; 404 is more secure for sensitive APIs.
IDE Shortcuts
The essentials: Ctrl+P (Quick Open files), Ctrl+Shift+P (Command Palette), Ctrl+F (Find), Ctrl+H (Find and Replace), Ctrl+D (Select next occurrence), Ctrl+Shift+K (Delete line), Alt+Up/Down (Move line), Ctrl+/ (Toggle comment), F12 (Go to Definition), and Ctrl+Shift+O (Go to Symbol in file).
VS Code updates can reset customized keybindings when the default "when" clause for a command changes. This is a known issue. To prevent it, define your custom keybindings in keybindings.json explicitly. If shortcuts stop working, run "Developer: Toggle Keyboard Shortcuts Troubleshooting" from the Command Palette to see what VS Code detects.
Open keybindings.json via Command Palette → "Preferences: Open Keyboard Shortcuts (JSON)". Each binding has a key, command, and optional when clause. For example: {"key": "ctrl+e", "command": "workbench.action.terminal.toggleTerminal"}. You can also use the GUI editor via "Preferences: Open Keyboard Shortcuts".
On Mac, Cmd replaces Ctrl for most shortcuts (e.g., Cmd+P instead of Ctrl+P). Alt becomes Option. Some shortcuts differ: F2 (Rename Symbol) works on all platforms, but Cmd+F2 on Mac changes all occurrences. Linux generally matches Windows shortcuts. Our tool shows shortcuts for all platforms side by side.
Ctrl+Space conflicts with the Windows input method switching shortcut (switching keyboard languages). To fix: go to Windows Advanced Keyboard Settings → Input language hot keys → Change Key Sequence → set to "Not assigned". On Mac, Ctrl+Space conflicts with Spotlight/input switching — use Cmd+I or remap in VS Code.
Press Ctrl+K Ctrl+S to open the Keyboard Shortcuts editor, which shows all commands and their current keybindings. You can search, filter, and edit shortcuts directly. Alternatively, run "Developer: Toggle Keyboard Shortcuts Troubleshooting" to log all dispatched keyboard shortcuts in real time.
Ctrl+D adds the next occurrence of the current word as a cursor. Ctrl+Shift+L selects all occurrences. Alt+Click adds a cursor at the click position. Ctrl+Alt+Up/Down adds cursors above/below. Shift+Alt+Drag creates a column (box) selection. Multi-cursor editing is one of the most powerful productivity features in modern editors.
Ctrl+1, Ctrl+2, Ctrl+3 switch to the 1st, 2nd, 3rd editor group. Ctrl+\ splits the editor. Ctrl+W closes the current editor. Ctrl+K Ctrl+Left/Right moves focus between editor groups. Use Ctrl+Tab to cycle through open editors in the current group.
F12 (Go to Definition), Ctrl+F12 (Go to Implementation), Shift+F12 (Find All References), Alt+F12 (Peek Definition), Ctrl+Hover (Peek Definition inline), Ctrl+- (Go Back), Ctrl+Shift+- (Go Forward), Ctrl+G (Go to Line), Ctrl+P (Quick Open file by name).
No questions found. Try a different search or filter.
Still have questions?