This tool runs entirely in your browser. Nothing you paste is uploaded.
How you can check →Log Extractor
Logs & DebuggingPaste a log, or drop one or more log files, and get every JSON, XML, escaped payload, Java map, Python dict, JWT, base64-encoded JSON and stack trace sitting inside it — pulled out with a real parser rather than brace-counting, with long trace IDs and order numbers kept exactly as logged. Runs entirely in this tab.
What it looks for
- JSON objects and arrays sitting anywhere in a line, not just lines that are JSON on their own
- XML and SOAP envelopes, confirmed well-formed before they're reported
- Long IDs kept exact — a 19-digit trace ID comes back with every digit intact
-
Up to 50 MB per file, streamed through a
worker so the page never freezes —
.gzfiles are decompressed in the same worker, so a rotated log never needs unzipping by hand first - JWTs and base64-encoded JSON decoded — header, payload and a one-click hand-off to the JWT decoder
- Secrets flagged before you share — tokens, keys and emails counted, and maskable everywhere
- Two payloads compared field by field, and any find sent on to another tool
Not sure what to paste? above to see it work.
No network activity while you use this tool Show the numbers
- Requests to any other server
- 0
- Requests since you started typing
- —
Counted live by your browser's own Performance Timeline — the same data the DevTools Network panel reads. It cannot see what a browser extension does, and it is not meant to replace checking for yourself: here is how, in thirty seconds .
What gets logged, and why it's unreadable
A production incident rarely hands you clean JSON. It hands you a log line where the
payload you need is squeezed between a timestamp, a thread name, a logger class and
a sentence of prose — outbound request: followed immediately by an
object with no space to breathe. A naive extractor that just counts { and
} characters breaks the moment a string value inside that payload
contains a brace of its own, which is common in exactly the kind of log people are
debugging: a regex pattern, an error message that quotes malformed input, a
stack-trace fragment logged as a string.
This tool starts from the same lossless JSON parser that runs every JSON tool on this site, asked from an offset in the middle of a much longer string rather than the start of a document. Because it's a real parser and not a scanner guessing at character counts, it knows the difference between a brace that opens a value and a brace sitting inside a quoted string, and it reports exactly where a payload ends.
Long trace IDs and order numbers survive
Every JSON extractor built on JSON.parse shares the same silent bug:
a number past 2^53 — 9,007,199,254,740,991 — gets rounded to the nearest value a
64-bit float can represent, and the extra digits are gone for good. A Snowflake ID
or an order number like 770368744177664001 comes back as
770368744177664000, which looks identical at a glance and is a
different number. That is a serious problem in a tool whose entire job is helping
you find and copy the ID you're chasing. This tool keeps the original characters:
a number is only ever re-typed if writing it back out produces the exact digits you
pasted, so long identifiers are returned unchanged.
JSON and XML, side by side
Enterprise integration logs are as often full of <soapenv:Envelope>
as they are JSON, and XML gets the same care: the tool confirms a candidate element
is genuinely well-formed — matching tag, valid attributes, a real closing tag —
before reporting it as a find. That check is what keeps a stray
<null> in prose, or a Java generic like
List<String>, from being mistaken for the start of a tag.
Escaped and double-escaped payloads
The single most common real-world form is a payload logged inside a JSON field of
its own, so it arrives as "payload":"{\"orderId\":123}" — quotes and
braces escaped, unreadable at a glance. This tool unescapes it, re-parses the
result, and shows it as its own find labelled unescaped. When a log
shipper or sidecar re-logs an already-escaped line, the payload can arrive
double-escaped; the same unescape step repeats until the text parses cleanly or
genuinely can't, and the find reports exactly how many layers it peeled off. To
unescape a payload by hand instead, paste just that field's value into the
JSON formatter.
Truncated payloads
Logging frameworks cap message length — Logback's %.-4096msg,
CloudWatch's 256 KB event limit, Splunk's default 10,000-byte
TRUNCATE — so a payload cut off mid-write is the normal outcome for
anything worth logging, not a rare edge case. A candidate that runs out of input
rather than closing cleanly is still reported as a find, labelled
TRUNCATED, with a plain diagnosis of exactly where it broke — "cut off
mid-string inside items[3].name" — rather than being silently dropped. The tool
does not guess at the missing characters and hand back a repaired payload; naming
where it broke is a fact, and inventing what came after would not be.
Java toString() and Python dicts
A Java Map.toString() or Lombok @ToString logs as
{orderId=123, status=PAID} — readable, but not JSON, and every
value in it is unquoted, untyped text. Once the log is recognised as Java, this
tool converts a Java map to JSON, inferring number versus string the same way the
rest of this site does — a value is only read as a number if writing it back out
produces the exact characters it started as, which is what keeps a 20-digit id or a
zero-padded code as a string. The class name on a Java 16 record or a Lombok
constructor is named in a caveat rather than silently dropped. A Python dict repr()
like {'id': 1, 'ok': True} gets the same treatment once the log
is recognised as Python — converting a Python dict to JSON online this way handles
True/False/None, tuples and bytes literals,
each flagged where it's lossy. Both readers only run once the log's own format is
actually detected as that language, gated by the "Looks like…" banner above the
results — a Java reader let loose on a Node log would be nothing but false
positives.
Stack traces, log format detection, and correlation ids
A Java, Python, Node, .NET or Go exception is captured as a single find rather than
forty separate log lines: the exception, its message, every frame, and the cause
chain, with the first frame that's your own code — not a framework's — promoted to
the top of the collapsed row. The same first pass that gates the reconstructions
above reads the log's own shape — "Looks like Java · Logback", shown with its
matched evidence lines so it's checkable in a couple of seconds, and "unrecognised"
is a plain, first-class answer rather than a guess. Above 50 finds, payloads sharing
the same structure are grouped automatically, and a group missing a field the
largest one has is flagged — often the actual bug. Any traceId,
requestId or similar id found on a line or inside a payload can be
picked from the "Correlate by" menu to filter straight down to one request's
events.
What gets reported, not just what gets extracted
Every scan reports how many lines and bytes it covered, how many payloads it found, and how many candidates it looked at but couldn't parse — a brace that turned out to be prose, a tag that didn't close cleanly. A tool that only shows you what it found, and says nothing about what it looked at and rejected, is not a tool you can trust about what it missed. If a scan hits its internal safety limits on a pathological input, that's stated too, rather than silently returning a partial result that looks complete.
Before you paste a log into a ticket
The most expensive thing in a log is rarely the payload you came for — it's the bearer token two lines above it, which is about to be attached to a Jira ticket that half the company can read. Because the tool has already read the whole file, it can say what's in there: how many JWTs, emails, password or token fields, AWS access keys, private-key blocks, card-shaped numbers and IP addresses it matched. Turn on Redact secrets and every one of them is masked everywhere the tool hands text back — on screen, in the clipboard, in a per-find download and in every export format, because a redaction that one download path forgets is worse than none. Download redacted log gives you a masked copy of the entire file rather than just the finds, generated in this tab: a "redact my log" service that uploads the unredacted log in order to do the work would be self-refuting.
This is pattern matching, and the page says so wherever it appears. It reports what it found; it never certifies what's left. A custom token format, an internal hostname, or a credential written into a sentence will not be caught, and no copy anywhere on this page will tell you a log is now safe to share. Redaction is also off until you ask for it — a tool that hides your own token from you in your own log reads as broken, and you'd go and paste the log into a worse one.
Comparing two payloads, and sending one onward
Once payloads are grouped by shape, the obvious next question is what actually
differs between two of them. Tick Compare on any two JSON finds and
the tool lists the JSON Pointers that differ: changed values, fields present on only
one side, and an array that grew reported as one row rather than as every subsequent
index having "changed". It compares the characters that were logged rather than the
parsed values, so 1.20 and 1.2 are a difference — in a log
they are — and a 19-digit id is compared digit for digit. The result copies as
readable text or as a list of change objects; it is deliberately not called a JSON
Patch, because it isn't one.
Every find can be sent onward: a JSON payload opens in the JSON formatter, an XML one in the XML to JSON converter, and a JWT spotted inside a payload in the JWT decoder. A whole shape group can be flattened to CSV — one row per payload, one column per leaf — and handed to the table workbench, which turns 1,180 near-identical payloads into something sortable. Anything too large for a link goes by way of the clipboard with a note saying so, rather than being quietly truncated on the way. All finds can also be exported at once as JSON, NDJSON or raw text, in source order, filters and grouping notwithstanding.
Multiple files, one scan
Rotated logs arrive as app.log, app.log.1,
app.log.2 — drop all of them at once and they're scanned one after
another, in the order you dropped them, which you can reorder before starting. Once
more than one file is loaded, every find is tagged with the file it came from, so
the results stay traceable back to a specific file even after they're mixed together
in one list.
Big files, and your browser
A dropped file is handed to a Web Worker, which reads it as a stream rather than loading the whole thing into one JavaScript string on the page — the 40 MB log never sits in memory as a single value, so the tab stays responsive and the Cancel button actually works mid-scan. Log Extractor never uploads what you give it: reading, scanning and formatting all happen in this worker, on your machine, and there is no server for the file to be sent to. If your JSON is buried in a log rather than pasted whole, the JSON formatter and the XML to JSON converter are where an extracted payload goes next.
Frequently asked questions
- What does the log extractor actually pull out of my log?
- Every well-formed JSON object or array and every well-formed XML element sitting anywhere in the text — mid-line, indented inside a stack trace, wherever it appears — not just lines that are JSON on their own. It uses this site's existing lossless JSON parser started from the middle of a string, rather than a brace-counting scanner, so a brace inside a quoted value doesn't confuse it.
- Does it change long numbers like trace IDs or Snowflake IDs?
- No. A 19-digit order number or trace ID comes back exactly as it was logged, because the same parser that formats plain JSON on this site refuses to round-trip a number through JavaScript's 64-bit float unless doing so is provably safe. This is the reason the tool exists: every extractor built on JSON.parse silently rewrites the one value you were trying to look up.
- Can it read JSON that's escaped inside another log field, like "payload":"{\"id\":1}"?
- Yes. When a payload was serialised into a string field — the single most common real-world form — the tool unescapes it, re-parses it, and shows it as its own find labelled "unescaped". Logs that crossed two escaping boundaries (a sidecar re-logging an already-escaped line) are unescaped again automatically, and the find says exactly how many layers were peeled off, so nothing is presented as your original bytes when it isn't.
- What happens when a payload was cut off mid-line by the logging framework?
- It's reported as a find labelled TRUNCATED, with a plain-English diagnosis of exactly where the cut happened — "cut off mid-string inside items[3].name" — rather than being silently dropped as a rejected candidate. The tool does not guess at the missing characters and reconstruct a repaired payload; showing you where it broke is a fact, and inventing what came after it would not be.
- Does it read Java toString() maps or Python dict output?
- Yes, once the log is recognised as Java or Python. A Java map ("{orderId=123, status=PAID}"), a Java 16 record, or a Lombok toString() is reconstructed into JSON and labelled "reconstructed", with the types it inferred named as caveats rather than presented as fact. The same applies to a Python dict repr() ("{'id': 1, 'ok': True}"). Reconstruction only runs when the log's own format was actually detected as that language — a Java reader let loose on a Node log would be nothing but false positives.
- Does it decode JWTs and base64-encoded JSON sitting in a log line?
- Yes. A JWT anywhere in the text — bare in a log line or sitting inside a JSON field like "token":"eyJ..." — is decoded into its own find showing the header and payload as JSON, labelled "decoded from jwt", with a one-click hand-off to the site's JWT decoder. A base64 or base64url run that decodes to a JSON object or array gets the same treatment, labelled "decoded from base64" — a bare number or ordinary string that happens to be valid base64 is not reported, since almost any short base64 run decodes to something and reporting all of them would bury the real finds.
- Can it summarise a stack trace instead of showing forty lines of it?
- Yes. A Java, Python, Node, .NET or Go exception is captured as one find — the exception, its message, every frame, and the cause chain — with the first frame that is your own code (not a framework's) promoted to the top of the collapsed row. It's a heuristic, so it's labelled "first app frame", not "the cause": you get to the useful line faster without the tool pretending to have diagnosed the bug for you.
- What is the "Looks like Java · Logback" banner, and can I be wrong about it?
- It's a plain read of the first couple hundred lines against known log formats — Logback/Log4j2, Python's logging module, pino, winston, zap, Serilog, syslog, Docker/Kubernetes — shown with its evidence so you can check it in a couple of seconds. It only gates which reconstructions the tool attempts; JSON and XML extraction always run regardless, and an unrecognised format is shown honestly as "unrecognised" rather than guessed at.
- Can I group identical payload shapes, or follow one request across a log?
- Yes to both. Above 50 finds the tool automatically groups payloads that share the same structure, and flags when a smaller group is missing a field the largest one has — often the actual bug. Separately, any traceId, requestId, or similar correlation id found on a log line or inside a payload can be picked from a "Correlate by" menu to filter the whole result down to one request's events.
- Can it pull SOAP or other XML out of a log?
- Yes. XML gets the same treatment as JSON: a real parser confirms the element is well-formed before it's reported as a find, so a stray < in prose — a Java generic, a null placeholder, a “less than” in a sentence — doesn't get mistaken for the start of a tag.
- How large a log file can it handle?
- Up to 50 MB per file and up to 200 MB across a batch of up to 20 files. A dropped file is streamed and scanned inside a Web Worker rather than read into one giant string on the page, so the tab stays responsive and you can cancel mid-scan. Pasted text tops out at 10 MB, matching the paste limit used across the rest of the site's JSON tools.
- Does it accept .gz files, or do I have to unzip a rotated log first?
- It reads .gz directly. The browser's own DecompressionStream decompresses the file inside the same worker that scans it, so a compressed rotated log (app.log.2.gz) never touches disk unzipped and never leaves your device to be decompressed somewhere else. The 50 MB per-file limit is checked against the compressed size you drop, since the decompressed size isn't known until the file finishes streaming.
- Is my log uploaded anywhere?
- No. The file never leaves your device — it's read locally with the browser's own streaming file APIs, decoded, and scanned entirely on your machine. Open your browser's Network tab while you use it and watch it stay empty.
- Can I scan more than one log file at once?
- Yes. Drop several files — a rotated app.log, app.log.1, app.log.2 — and they're scanned one after another in the order you dropped them, which you can reorder before starting. Every find is tagged with the file it came from once more than one is loaded.
- Can it tell me what secrets are in a log before I paste it into a ticket?
- Yes — that's the audit. After a scan, the tool reports what it matched across the whole log: JWTs, emails, bearer and basic credentials, password and token fields, AWS-key-shaped strings, private-key blocks, card-shaped numbers that pass a Luhn check, and IP addresses. Turning on "Redact secrets" masks them everywhere the tool shows, copies, downloads or exports, and "Download redacted log" gives you a masked copy of the whole file — generated in your browser, never uploaded. This is pattern matching, so it says what it found and never that a log is now safe to share; a custom token format or a password written into a sentence will not be caught.
- Can I compare two payloads to see what changed?
- Yes. Tick Compare on any two JSON finds and the tool lists the pointers that differ — changed values, fields present on only one side, and array length changes as a single row rather than a cascade of shifted indices. It compares the characters that were logged rather than the parsed values, so 1.20 and 1.2 count as a difference, which in a log they are. The result copies as text or as a list of change objects.
- What does it show me if nothing is found?
- A plain statement that the scan completed and found no JSON or XML, along with how much of the file was actually scanned — never a blank results area with no explanation, which looks identical to a tool that's still loading or has silently failed.