YAML indentation and syntax checker with line numbers
Catch the structural slips that break a YAML file: in the sample, port repeated on line 4 after line 3 and a tab on line 5 give 2 findings, each with its line and a plain explanation. Free in your browser.
- Free
- Runs in your browser
- No sign-up
- Your data stays on your device
Run — free
Worked example
- Text
- service: name: api port: 8080 port: 9090 debug: true
- Error count
- 2
This YAML indentation and syntax checker catches the small structural mistakes that make configuration files unreliable: tabs hidden in leading whitespace, indentation that changes depth unexpectedly, and repeated keys inside the same mapping. Every finding includes its source line, so you can move directly from the report to the faulty setting. The checker also rejects text that cannot be interpreted as YAML at all, keeping malformed input distinct from a valid document that merely contains lint findings.
Read a focused report instead of chasing parser messages
Paste the complete YAML document into the text field and run the checker. The result states whether the document passed, gives the number of findings, and lists each problem with a one-based line number, a stable problem type, and an explanation. That compact shape works equally well for a person reviewing a deployment file and for a script checking generated configuration.
The checker concentrates on three frequent structural hazards. It identifies tabs used in leading whitespace, because tabs can render at different widths across editors. It identifies indentation changes that do not follow the structure already established by parent nodes.
It also tracks mapping keys by scope, so the same spelling may appear in separate objects while a repeated key in one object is reported. Comments and blank lines do not disturb the line references. A clean response has an empty errors array rather than placeholder values, which makes it straightforward to treat valid output as a successful gate in a build or pre-commit workflow.
Understand the difference between lint findings and invalid input
A lint finding describes text that can still be examined usefully even though its structure is risky. For example, a tab in indentation or a duplicate mapping key receives a normal result containing the relevant line. A parsing failure is different: the document is so incomplete or malformed that reliable structural analysis cannot continue.
Unterminated quotes, unmatched flow collection delimiters, empty mapping keys, or a plain line where a mapping or sequence node is required cause an invalid-input error. Keeping these outcomes separate is useful in automation. Your integration can display every recoverable finding at once, while a parsing failure can stop the pipeline and ask the producer to repair the source.
The check is deterministic and does not rewrite the document, choose a duplicate value, or guess the intended nesting. That restraint matters for configuration, where silently changing meaning is often worse than rejecting a file. Fix the earliest parsing failure first, run the check again, and then work through any line-numbered lint findings that remain.
What you can do with it
Check deployment configuration
Catch shifted nesting, tabs, and repeated settings before a deployment tool interprets the file.
Validate generated YAML
Inspect template output in a build and return actionable line numbers when generation produces malformed structure.
Review configuration changes
Add a fast structural check to code review so subtle whitespace errors do not hide inside a large diff.
FAQ
What does a check cost?
The browser version can be used directly on this page.
Does the checker modify my YAML?
No. It only reports findings and never rewrites indentation, removes keys, or chooses between duplicate values.
Are duplicate keys allowed in different objects?
Yes. A key is reported only when it repeats within the same mapping scope; the same key can appear in separate nested objects.
Why are tabs reported even when the file looks aligned?
Editors can display tabs at different widths, so visually aligned YAML may acquire different nesting when moved between tools.
What is the difference between a finding and a rejected file?
A finding, such as a tab or a repeated key, still gets a normal report with its line. Text too broken to analyze, such as an unclosed quote or an empty key, is rejected outright, so fix that first and check again.
Related tools
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/dev2/yaml-lint-basic \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"service:\n name: api\n ports:\n - 8080\n - 8081"}'const res = await fetch("https://api.kit.forhosting.com/dev2/yaml-lint-basic", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"text": "service:\n name: api\n ports:\n - 8080\n - 8081"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/dev2/yaml-lint-basic",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"text": "service:\n name: api\n ports:\n - 8080\n - 8081"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/dev2/yaml-lint-basic", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"text":"service:\\n name: api\\n ports:\\n - 8080\\n - 8081"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"text":"service:\n name: api\n ports:\n - 8080\n - 8081"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/dev2/yaml-lint-basic", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"text": "service:\n name: api\n ports:\n - 8080\n - 8081"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "dev2.yaml_lint_basic",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |
Technical notes
Use the checker safely in editors and delivery pipelines
Send the exact source text rather than a parsed object, because indentation and duplicate keys disappear after many parsers convert YAML into ordinary data. Preserve line endings and comments if you want report positions to match the file in your editor. The endpoint is designed for quick checks before YAML reaches a deployment tool, package publisher, continuous integration job, or application startup. A practical pipeline can run this check after templating but before secrets are injected, then fail when valid is false or when the request returns an invalid-input error. The response is stable for identical text: it uses no network access, randomness, clock, or environment-specific state. It also applies bounded input and line limits so accidental oversized documents cannot create unbounded work. This is intentionally a basic structural lint, not a schema validator. It does not know whether a Kubernetes field, workflow property, or application option is allowed. Pair it with the schema-aware validator for your target system when semantic correctness matters, and use this checker for the universal YAML mistakes that occur before domain rules can help.
Technical questions
Is this a Kubernetes or workflow schema validator?
No. It checks general YAML structure and basic syntax, not product-specific field names, types, or policy rules.