Cyclomatic complexity calculator
The cyclomatic complexity API computes McCabe's metric from the structure of a control-flow graph: you supply the number of edges, the number of nodes, and the number of connected components, and it returns the cyclomatic complexity M = E − N + 2P, the minimum number of linearly independent paths through the code and a lower bound on the test cases needed for full branch coverage. No source code to upload, no parser to configure — just three counts from the graph you already have, and one deterministic number back, computed the same way in your browser and on our edge.
Run — free
What cyclomatic complexity measures
Cyclomatic complexity, introduced by Thomas McCabe in 1976, counts the number of linearly independent paths through a program's control-flow graph. Every decision point — an if, a while loop, a case branch, a conditional expression — adds one path, so the metric tracks how hard a piece of code is to test and to reason about. A value of 1 means straight-line code with no branches at all. A value of 10 is the widely cited threshold above which a module starts to demand splitting. The number is a property of the graph, not of the language: once you have drawn the control-flow graph of a function, its complexity is fixed, and this cyclomatic complexity calculator evaluates it directly from the graph's three counts. Because the input is just edges, nodes and components, it works for pseudocode, flowcharts, and graphs exported from any static-analysis tool, with no need to share the source itself.
The formula M = E − N + 2P
The metric is computed as M = E − N + 2P, where E is the number of edges in the control-flow graph, N the number of nodes, and P the number of connected components. For a single program or function the graph is one connected component, so P = 1 and the formula reduces to M = E − N + 2. When you analyze several disconnected functions at once — say, the call graphs of three separate modules drawn in one diagram — P counts each disconnected piece and the +2P term keeps the result consistent with summing the complexities of the parts. The endpoint also returns decision_points, defined as M − 1, which equals the number of predicates in a structured program whose graph you measured. All three inputs must be positive integers; the call rejects fractions, zero, negative counts and non-numeric values, because such counts cannot describe a real control-flow graph and silently accepting them would hide a measurement mistake upstream.
Using the number in practice
The complexity tells you the minimum number of test cases needed to exercise every independent path, so teams use it as a coverage floor in test planning: a function with M = 7 cannot be fully branch-tested with three tests no matter how cleverly they are chosen. It also feeds code-review policy — many shops flag any function whose complexity rises above an agreed limit — and technical-debt tracking, where the sum or maximum over a codebase is watched release over release. This API is the arithmetic step of that workflow: count the edges, nodes and components from your analyzer or diagram, send them in, and get the same value every time, since the computation is fully deterministic with no rounding and no heuristics. It runs on our global edge at $0.002 per request, and the identical code runs free in your browser on this page, so you can verify a figure by hand and only pay when you automate the check in a pipeline.
What you can do with it
Set a test coverage floor
Turn the graph counts from your static analyzer into the minimum number of test cases required to cover every independent path of a function.
Enforce a complexity budget in CI
Fail a build when a module's cyclomatic complexity crosses the team's agreed threshold, computed from edges, nodes and components.
Check homework and exam answers
Verify the result of a software-engineering exercise that asks for McCabe's number from a given flowchart, with the formula shown in the response.
FAQ
What does it cost?
$0.002 per request. It is also free to run in your browser on this page — the same code computes both.
What formula is used?
McCabe's original formula M = E − N + 2P, where E is edges, N is nodes and P is connected components. For a single program P = 1, so it is E − N + 2.
Why are my inputs rejected?
Edges, nodes and components must each be a positive integer. Zero, negative numbers, fractions and non-numeric values cannot describe a real control-flow graph and are rejected as invalid input.
What is the decision_points field?
It is M − 1: the number of predicate (decision) nodes in a structured program whose graph has this complexity. It is a convenience for teams that count ifs and loops instead of edges.
Do I need to send source code?
No. The input is three counts from the control-flow graph, so proprietary code never leaves your analyzer — only its edge, node and component totals travel.
Is the result deterministic?
Yes. It is exact integer arithmetic with no rounding, randomness or external calls: the same three counts always return the same complexity.
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/math/cyclomatic-complexity \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"edges":9,"nodes":8,"components":1}'const res = await fetch("https://api.kit.forhosting.com/math/cyclomatic-complexity", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"edges": 9,
"nodes": 8,
"components": 1
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/math/cyclomatic-complexity",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"edges": 9,
"nodes": 8,
"components": 1
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/math/cyclomatic-complexity", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"edges":9,"nodes":8,"components":1}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"edges":9,"nodes":8,"components":1}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/math/cyclomatic-complexity", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"edges": 9,
"nodes": 8,
"components": 1
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "math.cyclomatic_complexity",
"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. |