# Fire Sprinkler Hydraulic Calculator (NFPA 13) (`jumblemog/sprinkler-hydraulics-calculator`) Actor

Fire sprinkler hydraulics from plain text: NFPA 13 density/area demand, a tree system worked from the remote sprinkler to the supply with Hazen-Williams friction and fittings, the water supply check, and pipe friction loss.

- **URL**: https://apify.com/jumblemog/sprinkler-hydraulics-calculator.md
- **Developed by:** [Jumble Mog](https://apify.com/jumblemog) (community)
- **Categories:** AI, Automation, Developer tools
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Fire Sprinkler Hydraulic Calculator (NFPA 13)

**Run an NFPA 13 sprinkler hydraulic calculation, size a hazard's water demand, or find the friction loss in a pipe, from one line of text.** Ask `light hazard office, K5.6 sprinklers 15x15 ft spacing, 4 in feed main 100 ft, 20 ft high, 70/50 psi at 1000 gpm` or `150 gpm through 100 ft of 2 in schedule 40 with 2 elbows and a tee` and you get back:

- **The design criteria**: density and design area for the hazard (light, ordinary group 1 or 2, extra group 1 or 2, or an occupancy such as "office" or "warehouse"), the sprinklers in the design area, how many per branch line, and the flow and pressure the end sprinkler needs.
- **The hydraulic calculation**: the most remote branch line worked sprinkler by sprinkler, the other lines by their K-factor, the cross main, the feed main with its fittings and elevation: flow, pipe size, friction, velocity and pressure at every node.
- **The demand at the supply**: sprinkler flow and pressure, the hose allowance, total flow, duration and water volume.
- **The water supply check**: the pressure your flow test gives at that demand and the safety margin.
- **Pipe friction loss**: Hazen-Williams loss per foot and in total, the fittings' equivalent lengths, elevation and velocity.
- **Charts** (pressure along the path and the hydraulic graph on N^1.85 paper) and a **Markdown report**.

It's made for:

- Fire protection designers, sprinkler contractors and engineers checking a layout or a flow test before the full calculation.
- Plan reviewers, inspectors, building owners and students learning how sprinkler hydraulics work.
- AI agents and building apps that need sprinkler demand and friction numbers they can show their work for.

![A chart made by this Actor for a light hazard system: the pressure rising from 16.1 psi at the end sprinkler to 55.9 psi at the supply, and the water supply curve from a 70/50 psi at 1,000 gpm flow test above the 298 gpm demand point with 12 psi to spare](https://api.apify.com/v2/key-value-stores/Km5b4PG3kYHdZSb1E/records/sprinkler-hydraulics-calculator-example.png?signature=QjLEvQwHVXjDlxtWh9ih)

### How to use it

1. Write **Systems, demands and pipes**, one per entry. The form has examples.
2. Optionally change the **Default hazard** (ordinary hazard group 1) or the **Default pipe** (Schedule 40 steel).
3. Click **Start**. Each request is a row in the results, with its summary, chart and report.

#### What you can write

| You write | It means |
|---|---|
| `light hazard`, `OH2`, `extra hazard group 1`, `office`, `warehouse` | The hazard (NFPA 13 density/area curve and hose allowance) |
| `0.20 gpm/ft2 over 2000 sq ft`, `0.15/1500` | Your own density and design area |
| `15x15 ft spacing`, `12 x 10 heads` | Sprinkler spacing along the branch lines × between them |
| `K5.6`, `K8.0`, `k-factor 11.2` | Sprinkler K-factor (5.6 by default, 8.0 for extra hazard) |
| `1 in branch lines`, `2-1/2 in cross main`, `4 in feed main` | Pipe sizes (the NFPA 13 pipe schedule when left out) |
| `feed main 100 ft`, `20 ft high` | Feed main length and sprinkler height above the supply |
| `70/50 psi at 1000 gpm`, `static 70 psi, residual 50 psi at 1,000 gpm` | The water supply flow test |
| `dry system`, `sch 10`, `cpvc`, `copper`, `C=100` | System type and pipe |
| `250 gpm hose`, `no hose`, `backflow 8 psi` | Hose allowance and a backflow preventer loss |
| `150 gpm through 100 ft of 2 in`, `2 elbows and a tee`, `rise 10 ft` | A single pipe's friction loss |

The same as an object: `{"hazard": "OH1", "spacing": "12 x 10", "k": 5.6, "branchSize": "1-1/4", "crossSize": "2-1/2", "feedLength": "200 ft", "elevation": 30, "static": 80, "residual": 60, "testFlow": 1500}`.

### Examples

- `light hazard office, K5.6 sprinklers 15x15 ft spacing, 4 in feed main 100 ft, 20 ft high, 70/50 psi at 1000 gpm` → 7 sprinklers on 2 branch lines, end sprinkler 22.5 gpm at 16.1 psi, 198 gpm at 55.9 psi at the supply (298 gpm with hose); the supply gives 67.9 psi there, 12.0 psi to spare.
- `ordinary hazard group 2 warehouse, 10x13 ft spacing, static 65 psi, residual 45 psi at 1200 gpm` → 402 gpm at 81.0 psi needed against 58.5 psi available: 22.5 psi short, so larger pipes or a fire pump.
- `extra hazard group 1 demand` → 0.30 gpm/ft² over 2,500 ft², 25 sprinklers, at least 750 gpm plus 500 gpm of hose, 112,500 gallons for 90 minutes.
- `friction loss 150 gpm through 100 ft of 2 in schedule 40 with 2 elbows and a tee` → 0.1989 psi/ft over 120 ft equivalent: 23.87 psi, 14.3 ft/s.

### How-to examples

Each example is a complete input; the results are from runs of the Actor (also listed under **Examples**).

#### How to run an NFPA 13 sprinkler hydraulic calculation

```json
{"requests": ["light hazard office, K5.6 sprinklers 15x15 ft spacing, 4 in feed main 100 ft, 20 ft high, 70/50 psi at 1000 gpm"]}
```

Result: 7 sprinklers on 2 branch lines, the end sprinkler at 22.5 gpm and 16.1 psi, and 198 gpm at 55.9 psi at the supply (298 gpm with hose). The supply gives 67.9 psi there, 12.0 psi to spare.

#### How to check if a water supply is enough for a sprinkler system

```json
{"requests": ["ordinary hazard group 2 warehouse, 10x13 ft spacing, static 65 psi, residual 45 psi at 1200 gpm"]}
```

Result: 402 gpm at 81.0 psi needed against 58.5 psi available: 22.5 psi short, so larger pipes or a fire pump.

#### How to calculate friction loss in sprinkler pipe (Hazen-Williams)

```json
{"requests": ["friction loss 150 gpm through 100 ft of 2 in schedule 40 with 2 elbows and a tee"]}
```

Result: 0.1989 psi/ft over 120 ft equivalent length: 23.87 psi, at 14.3 ft/s.

#### How to let an AI agent run sprinkler calculations

Add this Actor to the [Apify MCP server](https://mcp.apify.com) with `https://mcp.apify.com/?tools=jumblemog/sprinkler-hydraulics-calculator`. The agent passes the hazard, spacing and supply in one line and answers with the demand, the pressure at the supply and the safety margin.

### FAQ

**Which standard does it follow?** NFPA 13 (2022): density/area curves, hose allowances, the Hazen-Williams formula and fitting equivalent lengths.

**Can it give just the water demand for a hazard?** Yes: `extra hazard group 1 demand` gives 0.30 gpm/ft² over 2,500 ft², 25 sprinklers, at least 750 gpm plus 500 gpm of hose, and 112,500 gallons for 90 minutes.

**Does it use my flow test?** Yes. Give the static and residual pressures at a flow and it checks the supply at the demand.

**Is it a substitute for a stamped hydraulic calculation?** No. It's a quick check for layouts, bids and supply questions; submittals need a full calculation by a qualified designer.

### Input

| Field | What it is |
|---|---|
| `requests` | Systems, demands or pipes, as lines of text or objects (up to 200 per run) |
| `hazard` | Hazard when a request gives neither a hazard nor a density |
| `material` | Pipe when a request doesn't say |
| `charts` | Draw a chart for each request (default on) |

### Output

One dataset item per request, also saved together in the run's `OUTPUT` record:

```json
{
  "request": 1, "status": "ok", "type": "system", "title": "Light hazard sprinkler hydraulic calculation",
  "summary": "Light hazard, 0.1 gpm/ft² over 1,500 ft²: 7 K5.6 sprinklers at 15 x 15 ft on 2 branch lines; end sprinkler 22.5 gpm at 16.1 psi. Demand at the supply: 198 gpm at 55.9 psi, 298 gpm with 100 gpm of hose. The supply gives 67.9 psi there: 12.0 psi to spare.",
  "design": {"hazard": "Light hazard", "density": 0.1, "designArea": 1500, "coverage": 225, "kFactor": 5.6, "sprinklers": 7,
             "sprinklersPerLine": 4, "branchLines": 2, "endHeadFlow": 22.5, "endHeadPressure": 16.14},
  "demand": {"sprinklerFlow": 197.7, "pressureAtSupply": 55.86, "hoseAllowance": 100, "totalFlow": 297.7, "duration": 30},
  "supply": {"static": 70, "residual": 50, "testFlow": 1000, "availableAtDemand": 67.87, "safetyMargin": 12.01, "adequate": true},
  "segments": [{"from": "S1", "to": "S2", "flow": 22.5, "size": "1", "length": 15, "frictionPerFt": 0.162, "friction": 2.427, "pressure": 18.57}, "..."],
  "units": {"flow": "gpm", "pressure": "psi", "length": "ft", "diameter": "in", "velocity": "ft/s"}
}
```

A system also has `pipes`, `branchLines` and `remoteLine`; a demand has `design` and `demand`; a pipe has `pipe` and `fittings`. Every item has `warnings`, `notes` (every assumption and default), a Markdown `report` and links to the chart and report. A request that can't be computed has `"status": "failed"` and the reason in `error`, and isn't billed.

### How it works

1. **Criteria**: the density and smallest design area of the hazard's curve (NFPA 13 Figure 19.3.3.1.1), 30% more area for dry systems, hose allowance and duration from Table 19.3.3.1.2.
2. **Design area**: area ÷ coverage sprinklers, with 1.2 √A of it along the branch lines.
3. **End sprinkler**: flow = density × coverage, pressure = (Q / K)², at least 7 psi.
4. **Branch line**: back to the cross main, each sprinkler flowing K √P and each pipe losing 4.52 Q^1.85 / (C^1.85 d^4.87) psi per foot; the other lines flow by the first line's K-factor at the cross main pressure.
5. **Feed main**: friction over its length plus the fittings' equivalent lengths (Table 28.2.3.1.1, corrected for C and inside diameter), 0.433 psi per foot of height, any backflow loss.
6. **Supply**: available pressure = static − (static − residual) × (Q / test flow)^1.85, compared at the demand with hose.

### Pricing

You pay one low price per request, at the price shown on this page: a system calculation, a hazard demand, or a pipe's friction loss. The charts and report are included. Requests that can't be computed are never charged. If you set a maximum cost per run, the Actor stops before a request that wouldn't fit.

### Speed

A request takes milliseconds. A run through the API answers in about 10 seconds, including the cloud container starting.

### Tips and limits

- **A check, not stamped plans.** Real systems are calculated over the actual layout by a qualified designer and approved by the authority having jurisdiction; use this to size and check before that.
- **Tree systems** with identical branch lines on one side of the cross main; gridded and looped systems, in-rack sprinklers, storage (ESFR, CMSA) and residential (NFPA 13R/13D) design aren't covered.
- **Pipe schedule sizes** are the starting point when you leave sizes out; give your sizes to calculate your layout.
- **Limits**: 200 requests per run.

### For AI agents and developers

This Actor works with the [Apify MCP server](https://mcp.apify.com), so AI agents can call it as a tool. Pass `requests` as plain text and read `summary`, `design`, `demand`, `supply` and `warnings`. A direct API call that waits for the answer:

```bash
curl -X POST "https://api.apify.com/v2/acts/jumblemog~sprinkler-hydraulics-calculator/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"requests": ["ordinary hazard group 1 parking garage, 12x10 ft spacing, 60/40 psi at 900 gpm", "300 gpm through 250 ft of 4 in sch 10"]}'
```

`run-sync` instead returns the run's `OUTPUT`: the status, the counts and every result as JSON.

In Python, with the `apify-client` package:

```python
from apify_client import ApifyClient

client = ApifyClient("YOUR_TOKEN")
run = client.actor("jumblemog/sprinkler-hydraulics-calculator").call(run_input={
    "requests": [{"hazard": "LH", "spacing": "14 x 14", "feedLength": "120 ft", "static": 75, "residual": 55, "testFlow": 1100}],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["summary"])
```

### Credits

- Method: NFPA 13, *Standard for the Installation of Sprinkler Systems* (2022): density/area curves, hose allowances, pipe schedule, Hazen-Williams formula and fitting equivalent lengths. This Actor is not affiliated with the NFPA.
- Charts: [Vega-Lite](https://vega.github.io/vega-lite/) and [vl-convert](https://github.com/vega/vl-convert) (BSD-3-Clause), with the [Inter](https://rsms.me/inter/) font (SIL Open Font License).

# Actor input Schema

## `requests` (type: `array`):

One request per entry, as a line of text or an object. System: the hazard ('light hazard', 'OH2', 'extra hazard group 1', or an occupancy such as 'office' or 'warehouse') or a density ('0.20 gpm/ft² over 2000 sq ft'), the sprinkler spacing ('12x15 ft spacing': along the branch lines x between them) and any of: K-factor ('K5.6', 'K8.0'), pipe sizes ('1 in branch lines', '2-1/2 in cross main', '4 in feed main'; the NFPA 13 pipe schedule by default), feed main length ('feed main 100 ft'), sprinkler height above the supply ('20 ft high'), the flow test ('70/50 psi at 1000 gpm' or 'static 70 psi, residual 50 psi at 1000 gpm'), 'dry system', pipe ('sch 10', 'cpvc', 'copper', 'C=100'), hose ('250 gpm hose', 'no hose'), backflow loss ('backflow 8 psi'). Demand: a hazard alone. Pipe: '150 gpm through 100 ft of 2 in schedule 40 with 2 elbows and a tee'. Object fields: type (system, demand, pipe), hazard, density, area, dry, k, coverage, spacing, spacingL, branchSize, crossSize, feedSize, feedLength, armLength, elevation, material, c, static, residual, testFlow, hose, backflow, flow, size, length, fittings, title, text.

## `hazard` (type: `string`):

Hazard when a request gives neither a hazard nor a density (ordinary hazard group 1 by default).

## `material` (type: `string`):

Pipe when a request doesn't say (Schedule 40 steel by default).

## `charts` (type: `boolean`):

The pressure along the calculated path and the water supply graph, the demand, or friction loss curves.

## Actor input object example

```json
{
  "requests": [
    "light hazard office, K5.6 sprinklers 15x15 ft spacing, 4 in feed main 100 ft, 20 ft high, 70/50 psi at 1000 gpm",
    "ordinary hazard group 2 warehouse, 10x13 ft spacing, static 65 psi, residual 45 psi at 1200 gpm",
    "extra hazard group 1 demand",
    "friction loss 150 gpm through 100 ft of 2 in schedule 40 with 2 elbows and a tee",
    {
      "hazard": "OH1",
      "spacing": "12 x 10",
      "k": 5.6,
      "branchSize": "1-1/4",
      "crossSize": "2-1/2",
      "feedLength": "200 ft",
      "elevation": 30,
      "static": 80,
      "residual": 60,
      "testFlow": 1500
    }
  ],
  "charts": true
}
```

# Actor output Schema

## `results` (type: `string`):

One row per request: the summary and chart.

## `output` (type: `string`):

The OUTPUT record: every result in one JSON object.

## `files` (type: `string`):

Charts (PNG and SVG) and Markdown reports in the run's key-value store.

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "requests": [
        "light hazard office, K5.6 sprinklers 15x15 ft spacing, 4 in feed main 100 ft, 20 ft high, 70/50 psi at 1000 gpm",
        "ordinary hazard group 2 warehouse, 10x13 ft spacing, static 65 psi, residual 45 psi at 1200 gpm",
        "extra hazard group 1 demand",
        "friction loss 150 gpm through 100 ft of 2 in schedule 40 with 2 elbows and a tee",
        {
            "hazard": "OH1",
            "spacing": "12 x 10",
            "k": 5.6,
            "branchSize": "1-1/4",
            "crossSize": "2-1/2",
            "feedLength": "200 ft",
            "elevation": 30,
            "static": 80,
            "residual": 60,
            "testFlow": 1500
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("jumblemog/sprinkler-hydraulics-calculator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "requests": [
        "light hazard office, K5.6 sprinklers 15x15 ft spacing, 4 in feed main 100 ft, 20 ft high, 70/50 psi at 1000 gpm",
        "ordinary hazard group 2 warehouse, 10x13 ft spacing, static 65 psi, residual 45 psi at 1200 gpm",
        "extra hazard group 1 demand",
        "friction loss 150 gpm through 100 ft of 2 in schedule 40 with 2 elbows and a tee",
        {
            "hazard": "OH1",
            "spacing": "12 x 10",
            "k": 5.6,
            "branchSize": "1-1/4",
            "crossSize": "2-1/2",
            "feedLength": "200 ft",
            "elevation": 30,
            "static": 80,
            "residual": 60,
            "testFlow": 1500,
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("jumblemog/sprinkler-hydraulics-calculator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "requests": [
    "light hazard office, K5.6 sprinklers 15x15 ft spacing, 4 in feed main 100 ft, 20 ft high, 70/50 psi at 1000 gpm",
    "ordinary hazard group 2 warehouse, 10x13 ft spacing, static 65 psi, residual 45 psi at 1200 gpm",
    "extra hazard group 1 demand",
    "friction loss 150 gpm through 100 ft of 2 in schedule 40 with 2 elbows and a tee",
    {
      "hazard": "OH1",
      "spacing": "12 x 10",
      "k": 5.6,
      "branchSize": "1-1/4",
      "crossSize": "2-1/2",
      "feedLength": "200 ft",
      "elevation": 30,
      "static": 80,
      "residual": 60,
      "testFlow": 1500
    }
  ]
}' |
apify call jumblemog/sprinkler-hydraulics-calculator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,jumblemog/sprinkler-hydraulics-calculator"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/ukXy1YwFGTijgZDs8/builds/YkoWZMOGlehcQ68WZ/openapi.json
