legal.court-fee Unreviewed
The court fee to issue a money claim in England and Wales, from the claim value bands in force on a date.
1.0.2 · published 2026-10-03 by charlie · Anterra
Pinned by 27 tests, run in TypeScript, Python and Rust.
Unreviewed. This capability’s implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified solicitor has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.
Not professional advice. This capability calculates legal figures from published rules. It is a software component for developers, not legal advice. Rules change and every rate here has an effective date. Check that the dates cover your case. Verify results against the official sources listed in its README, and have a solicitor review how you use it, before anyone relies on the output. Provided “as is” under its licence, without warranty.
What it does
The fee to start a claim for a specified sum of money in the County Court or the High Court of England and Wales (fee 1.1 of Schedule 1 to the Civil Proceedings Fees Order 2008), for the date the claim is issued.
**The value** is the amount claimed **including the interest claimed** to the date of issue, as the Order and the EX50 guidance say; add them before calling. Band edges belong to the lower band: a claim of exactly GBP 300 pays the "does not exceed GBP 300" fee, GBP 300.01 the next one.
For example
court_fee(£300.00, paper, 2026-09-23)→ £35.00 a GBP 300 claim is in the 'does not exceed 300' band: 35court_fee(£300.01, paper, 2026-09-23)→ £50.00 one penny more is the next band: 50court_fee(£1,200.00, paper, 2026-09-23)→ £80.00 GBP 1,200 is 80
The function
The same function in TypeScript, Python and Rust, pinned by the same tests. Pick your language; the choice follows you around the registry.
pub fn court_fee(claim: &Money, channel: &str, on_date: &str) -> Money
| claim | Money | the amount claimed, interest included, in GBP |
| channel | FilingChannel | paper, or online (Money Claim Online, Online Civil Money Claims, the County Court Business Centre) |
| on_date | date | the date the claim is issued |
| returns | Money |
The type it declares, generated into your project
// FilingChannel is a string in Rust, one of: "paper", "online".
// Parameters take it as &str and results hold it as String.
Your code names it in one line, in the file that uses it
fune!(legal.court-fee@^1); // then call court_fee(…)
Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::legal_court_fee_data::{ISSUE_FEES, ISSUE_FEES_HISTORY}; ← this capability’s own data, compiled from data/issue-fees.json into the same file by fune build
use super::money_amount::{money, money_from_value, money_to_value, Money}; ← from money.amount ^1.0.0 · built alongside by fune
use super::money_apply_rate::apply_rate; ← from money.apply-rate ^1.0.0 · built alongside by fune
fn is_iso_date(s: &str) -> bool {
let b = s.as_bytes();
b.len() == 10
&& b.iter().enumerate().all(|(i, c)| if i == 4 || i == 7 { *c == b'-' } else { c.is_ascii_digit() })
}
/// The fee to issue a money claim, from the bands in force on the issue date.
///
/// # Panics
/// Panics on a non-GBP or non-positive claim, an unknown channel, a bad date,
/// a date before the data, or an online claim over GBP 100,000.
pub fn court_fee(claim: &Money, channel: &str, on_date: &str) -> Money {
if claim.currency != "GBP" {
panic!("court fees are set for claims in GBP, received {}", claim.currency);
}
if claim.minor <= 0 {
panic!("claim must be greater than zero");
}
if channel != "paper" && channel != "online" {
panic!("unknown filing channel \"{}\": expected paper or online", channel);
}
if !is_iso_date(on_date) {
panic!("onDate must be an ISO date (YYYY-MM-DD), received \"{}\"", on_date);
}
let mut in_force = 0;
let mut earliest: Option<&str> = None;
for row in ISSUE_FEES {
if row.channel != channel {
continue;
}
if earliest.map_or(true, |e| row.valid_from < e) {
earliest = Some(row.valid_from);
}
if on_date < row.valid_from || row.valid_to.map_or(false, |to| on_date > to) {
continue;
}
in_force += 1;
if claim.minor <= row.over_minor || row.up_to_minor.map_or(false, |up| claim.minor > up) {
continue;
}
if let Some(fee) = row.fee_minor {
return money(fee, "GBP");
}
// gov.uk: "round down the result to the nearest 1 pence".
return apply_rate(claim, row.basis_points.unwrap(), "down");
}
if in_force > 0 {
panic!(
"a claim of {} pence cannot be issued {} on {}: online claims are limited to GBP 100,000",
claim.minor, channel, on_date
);
}
if let Some(e) = earliest {
if ISSUE_FEES_HISTORY != "full" && on_date < e {
panic!(
"no {} court fee on {}: this build was installed with history={}, so it only carries fees from {}. Reinstall with history=full for older claims.",
channel, on_date, ISSUE_FEES_HISTORY, e
);
}
}
panic!("no {} court fee in force on {}", channel, on_date);
}
pub fn fune_vector(args: &[Value]) -> Value {
money_to_value(&court_fee(&money_from_value(&args[0]), args[1].as_str(), args[2].as_str()))
}Install
fune build
With that line in your source, in a Rust project (language rust in fune.project), fune build resolves it and its 2 dependencies, pins them in fune.lock, downloads only the Rust package of each, and builds the code above into your project’s .fune/build, one readable file per capability with a header linking back here. A crate’s build.rs runs it before every compile. Or pin a range in fune.project and build in one step:
fune add legal.court-fee
The manifest, vectors and README with only the Rust implementation. Install it without the registry with fune add ./legal.court-fee-1.0.2-rust.fune, or fetch it from a terminal with fune pull legal.court-fee@1.0.2:rust.
The whole function, every language, is one file too: legal.court-fee-1.0.2.fune, 28,650 bytes, sha256 d2d7f4132bb6851de07bc03880325d69e4950c060408a88e2a930dacfa2c3724. It installs into a project of any language.
Customise it in your app
The seams this capability offers. Put a marker directly above a function of your own and fune build wires it into the built code; the package on the registry is not changed, the built file’s header lists it under CUSTOMISED, and fune hooks lists every hook in the project. How hooks work.
before — your function gets the arguments and returns them, changed or not, or throws to refuse the call.
// fune: before legal.court-fee
after — your function gets the result and the arguments, and returns the final result.
// fune: after legal.court-fee
replace — inside this capability’s code only, calls to a dependency go to your function, with the same signature. Other capabilities that use it are unaffected; write in * to replace it everywhere.
// fune: replace money.amount in legal.court-fee
// fune: replace money.apply-rate in legal.court-fee
step — your function runs at a numbered point inside the function’s body, receives the in-scope values it names as parameters, and may return replacements. List the points with fune show legal.court-fee --steps.
// fune: step legal.court-fee after <n|label>
Tests
A version published now needs at least 8 tests for every function, and one that expects the error for each function that throws; the registry refuses it otherwise. fune verify --all runs each case in TypeScript, Python and Rust, and a project runs them again with fune verify. This page lists the cases; it does not run them. The exact JSON is vectors.json.
| Case | Arguments | Expected | |
|---|---|---|---|
| a GBP 300 claim is in the 'does not exceed 300' band: 35 | £300.00, paper, 2026-09-23 | → | £35.00 |
| one penny more is the next band: 50 | £300.01, paper, 2026-09-23 | → | £50.00 |
| GBP 1,200 is 80 | £1,200.00, paper, 2026-09-23 | → | £80.00 |
| GBP 4,999.99 is 205 | £4,999.99, paper, 2026-09-23 | → | £205.00 |
| GBP 10,000 exactly is still the flat 455 | £10,000.00, paper, 2026-09-23 | → | £455.00 |
| GBP 10,000.01 is 5%, rounded down: 500.00 | £10,000.01, paper, 2026-09-23 | → | £500.00 |
| 5% of GBP 12,345.79 is 617.2895, rounded down to 617.28 (not up to 617.29) | £12,345.79, paper, 2026-09-23 | → | £617.28 |
| GBP 200,000 is 5%: exactly 10,000 | £200,000.00, paper, 2026-09-23 | → | £10,000.00 |
| over GBP 200,000 is a flat 10,000 | £750,000.00, paper, 2026-09-23 | → | £10,000.00 |
| online today pays the same as paper | £250.00, online, 2026-09-23 | → | £35.00 |
Show the other 17 tests
| Case | Arguments | Expected | |
|---|---|---|---|
| online today: GBP 50,000 is 5% | £50,000.00, online, 2026-09-23 | → | £2,500.00 |
| online on 17 May 2021 still had the lower fee 1.2: 25 | £250.00, online, 2021-05-17 | → | £25.00 |
| online from 18 May 2021 fee 1.2 is gone: 35 | £250.00, online, 2021-05-18 | → | £35.00 |
| online in 2020, GBP 7,500 was 410 | £7,500.00, online, 2020-06-01 | → | £410.00 |
| online in 2020, GBP 50,000 was 4.5%: 2,250 | £50,000.00, online, 2020-06-01 | → | £2,250.00 |
| online in 2020, 4.5% of GBP 10,000.99 is 450.04455, rounded down | £10,000.99, online, 2020-06-01 | → | £450.04 |
| paper in 2020 was already 35 up to GBP 300 | £250.00, paper, 2020-06-01 | → | £35.00 |
| the first day of the 2015 bands | £15,000.00, paper, 2015-03-09 | → | £750.00 |
| an online claim over GBP 100,000 is an error | £100,000.01, online, 2026-09-23 | → | error: cannot be issued online |
| an online claim over GBP 100,000 was an error under fee 1.2 too | £150,000.00, online, 2020-06-01 | → | error: cannot be issued online |
| before 9 March 2015 there is no data | £300.00, paper, 2015-03-08 | → | error: court fee |
| a claim in euros is an error | €300.00, paper, 2026-09-23 | → | error: court fees are set for claims in GBP |
| a zero claim is an error | £0.00, paper, 2026-09-23 | → | error: claim must be greater than zero |
| an unknown channel is an error | £300.00, fax, 2026-09-23 | → | error: unknown filing channel |
| a malformed date is an error | £300.00, paper, 23/09/2026 | → | error: onDate must be an ISO date |
| a date with a trailing newline is refused | £300.00, paper, 2026-09-23 | → | error: onDate must be an ISO date |
| a date in Arabic-Indic digits is refused | £300.00, paper, ٢٠٢٦-09-23 | → | error: onDate must be an ISO date |
More from the author
**Percentage bands.** Claims over GBP 10,000 and up to GBP 200,000 pay 5% of the claim; gov.uk's guidance is to "round down the result to the nearest 1 pence", so 5% of GBP 12,345.79 is GBP 617.28, not 617.29. Over GBP 200,000 the fee is a flat GBP 10,000. A claim whose value is not limited also pays GBP 10,000; pass any value over GBP 200,000 for it, or better, read the fee from the top band yourself.
**Paper and online.** From 9 March 2015 until 17 May 2021 claims issued through the County Court Business Centre or Money Claim OnLine paid the lower fee 1.2 (GBP 25 up to GBP 300 ... 4.5% from GBP 10,000 to GBP 100,000). The Civil Proceedings Fees (Amendment) Order 2021 (SI 2021/588) omitted fee 1.2 from 18 May 2021, so online claims now pay fee 1.1 like paper ones. Online services only take claims up to GBP 100,000 (Money Claim Online's limit is GBP 99,999.99), so an online claim above GBP 100,000 is an error rather than a fee.
**Rounding the 4.5% band down** as well is an assumption: the Order does not say, and gov.uk's rounding note is only for the 5% band.
Claims must be in GBP and more than zero. Dates before 9 March 2015 are an error: the bands before then (fee 1.1 as substituted in April 2014, with flat fees up to GBP 1,920) are not carried. Remission (help with fees), hearing fees, fees for non-money claims and the fees of other jurisdictions are out of scope.
## Sources
- The Civil Proceedings Fees Order 2008 (SI 2008/1053), Schedule 1, fee 1.1, latest version and the version at 17 May 2021: https://www.legislation.gov.uk/uksi/2008/1053/schedule/1 and https://www.legislation.gov.uk/uksi/2008/1053/schedule/1/2021-05-17 - The Civil Proceedings and Family Proceedings Fees (Amendment) Order 2015 (SI 2015/576), made 5 March 2015, in force on the next Monday, 9 March 2015: https://www.legislation.gov.uk/uksi/2015/576/made - The Civil Proceedings Fees (Amendment) Order 2021 (SI 2021/588), in force 18 May 2021: https://www.legislation.gov.uk/uksi/2021/588/made - HMCTS, "Civil court fees (EX50)", updated 13 July 2026: https://www.gov.uk/government/publications/fees-in-the-civil-and-family-courts-main-fees-ex50/civil-court-fees-ex50 - gov.uk, "Make a court claim for money: court fees" (rounding note): https://www.gov.uk/make-court-claim-for-money/court-fees
All read on 23 September 2026. When the fees change, that is a new version of this capability with a new row set; the rows declare their effective dates, so a `history=current` build keeps only today's fees and refuses an older date rather than answering it with them.
1.0.1 fixes Python accepting a trailing newline or non-ASCII digits in onDate; adds tests.
## Before you rely on this
**Not professional advice.** This capability calculates legal figures from published rules. It is a software component for developers, not legal advice. Rules change and every rate here has an effective date. Check that the dates cover your case. Verify results against the official sources listed above, and have a solicitor review how you use it, before anyone relies on the output. Provided "as is" under its licence, without warranty.
**Unreviewed.** This capability's implementations agree in every language and pass its published test vectors, which were worked out from the official sources cited. But no qualified solicitor has yet checked those vectors, or confirmed that the capability covers the cases it claims. Treat it as a draft. Do not use it for real people, money or decisions without your own expert review. Once a qualified reviewer signs off, this notice is replaced with their name, qualification and the date. Each new version needs fresh sign-off.
## Notices
Contains public sector information licensed under the Open Government Licence v3.0 (https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/).
Legislation: Crown copyright and database right.
1.0.2 marks it unreviewed and adds its attribution notices (NOTICE). The code and the tests are unchanged.
Files
| Path | Bytes |
|---|---|
| NOTICE | 228 |
| README.md | 4,534 |
| data/issue-fees.json | 6,488 |
| impl/python.py | 2,295 |
| impl/rust.rs | 2,740 |
| impl/typescript.ts | 2,144 |
| vectors.json | 5,684 |