JSON and YAML validator
Paste a document and find out exactly where it breaks: the line, the column, the byte offset, the offending line reprinted with a caret under the character the parser stopped on, and the most likely cause in plain words. Both formats are handled, and detection is automatic unless you say otherwise.
Paste JSON or YAML above to check it.
This page is not a formatter. It does not reindent anything and it gives you no output to copy. Its whole job is to say where a document is wrong and why. If what you want is tidy output, the JSON formatter beautifies and minifies, YAML to JSON and JSON to YAML convert between the two, and all three will tell you a document is invalid — they just will not show you a caret under the exact character or explain what usually causes it.
Your document stays in this tab. It is not uploaded, logged or stored — no cookie, no local storage, no history. The YAML parser is a copy of js-yaml served from this site, not from a third party.
Why a position is harder to get than it looks
Every JavaScript engine implements JSON.parse to the same specification and reports its failures differently. V8, in Chrome and Node, says something like Expected double-quoted property name in JSON at position 42 (line 3 column 1). Older V8 and JavaScriptCore gave the position and nothing else. SpiderMonkey, in Firefox, gives a line and a column but no offset. Some Safari releases give neither. A page that simply prints the exception therefore shows you a different amount of help depending on which browser you happened to open it in, which is a poor foundation for a debugging tool.
What this page does instead is extract whichever position the engine offered, convert it into a single internal form, and then compute the rest itself. A character offset becomes a line and a column by counting newlines. A line and a column becomes an offset by adding up line lengths. From the offset it slices out the offending line, reprints it, and builds a caret row underneath — with tabs copied through as tabs, so the marker still lands under the right character in a monospaced block rather than drifting eight columns to the left. The byte offset shown alongside is the UTF-8 byte count, not the character count, because that is what a server-side parser or a log line will usually be quoting at you.
The position a parser reports is where parsing became impossible, which is frequently not where the mistake is. A missing comma on line 12 is often reported at the start of line 13. A brace that never closed is reported at the very end of the file. That is why the caret is only half of what this page shows, and the heuristics below it are the other half.
The scan that runs alongside the parser
Whether or not the engine gave a position, a second pass walks the document character by character looking for the specific things people write when they mean JSON but are thinking in some other language. It tracks whether it is inside a string, so a comma inside a quoted value is not mistaken for a structural one, and every finding is reported at its own line and column rather than lumped into one message. It looks for a comma sitting before a closing brace or bracket, which JavaScript, Python and Rust all accept and JSON does not; strings quoted with apostrophes; keys written without quotes at all; // and /* */ comments, which JSON has never had; the literals NaN, Infinity and undefined, which are JavaScript values with no JSON spelling; True, False and None, which are Python's; and curly typographic quotes, which a word processor or a chat client inserted without telling you.
Duplicate keys get their own check, and it is the one worth having even when a document is perfectly valid. JSON.parse silently keeps the last of two identical keys and discards the earlier value without a word — JSON.parse('{"a": 1, "a": 3}').a is 3, and nothing anywhere tells you that a 1 was thrown away. The scan tracks object nesting separately from array nesting, so repeated keys across sibling objects in an array are not flagged, and a key that matches one in a parent object is not flagged either. Only a genuine repeat inside one mapping counts.
YAML is handled by js-yaml, served from this site rather than a content delivery network. It throws a YAMLException carrying a mark with a zero-based line and column, which this page converts to the one-based numbers editors use before drawing the same caret. On top of the parser's own message there is a line scan for the YAML-specific traps: tabs used for indentation, which the specification forbids outright; a colon with no space after it, so key:value is one plain string rather than a mapping; indentation that is not a multiple of the step the rest of the file uses; a plain value starting with a reserved character; a second colon inside an unquoted value; and the Norway problem, described below.
Questions people ask
How is this different from the JSON formatter on this site?
The formatter's job is output: it reindents, it minifies, and it gives you something to copy. It reports errors as a side effect, with the parser's own message and a line and column when the browser supplies one. This page produces no output at all. Instead it reprints the offending line with a caret under the failing character, gives the byte offset as well as the line and column, translates the engine's wording into an explanation of what usually causes it, and runs a separate scan for the mistakes that a parser cannot name because it stopped before it reached them. Use the formatter when you want tidy JSON. Use this when a document will not parse and you cannot see why.
Why does the caret point at the wrong place?
Because a parser reports where it gave up, not where you went wrong, and the two are often a line apart. A missing comma at the end of one line is discovered at the start of the next. An unclosed brace is discovered at the end of the file, since everything up to that point was still potentially valid. A missing closing quote swallows the rest of the line and fails somewhere further along entirely. Treat the caret as the end of the search rather than the beginning: read backwards from it, and check the additional findings listed underneath, which are located independently and often point at the real cause.
Are duplicate keys actually a problem if the document parses?
They are, and it is the most valuable check on this page precisely because nothing else complains. The JSON specification says the behaviour is undefined, and implementations disagree: JavaScript keeps the last, some Python configurations keep the last, some parsers raise an error, and a few keep the first. So a config file with a repeated key can behave one way in your test harness and another way in production, with nothing in either log to explain the difference. YAML takes the opposite view and rejects a duplicate key outright, which is why a document that JSON accepts quietly may fail loudly once someone converts it.
What is the Norway problem in YAML?
Under the YAML 1.1 rules, the unquoted words yes, no, on and off are booleans. A country list containing the ISO code for Norway, NO, therefore parses as the boolean false in PyYAML, in Ruby's parser and in a good deal of older tooling. YAML 1.2 narrowed booleans to true and false only, and js-yaml follows 1.2, so this page will show you no as the string it is. That difference is exactly the danger: the same file means two different things depending on which library reads it. The advice list flags these values on documents that parse perfectly well, because the fix is simply to quote them and the cost of not doing so is a bug nobody can reproduce.
Why are tabs banned in YAML indentation?
Because YAML's structure is its indentation, and a tab has no defined width. If a tab could count as indentation, the meaning of a document would depend on the tab width of whatever rendered it, and two people looking at the same file would see two different structures. The specification therefore forbids tabs in indentation entirely, and js-yaml raises an error the moment it finds one. Tabs are still perfectly legal inside a quoted scalar, where they are just characters. Almost every editor can be told to insert spaces in YAML files, and doing so removes the whole class of problem.