The U.S. Treasury publishes savings bond values through its Savings Bonds Value Files dataset. Its sb_value endpoint returns an issue year in each row, with separate amount fields for January through December.
That shape creates two easy data-import mistakes: treating a missing cell as zero, and converting decimal dollar strings through floating-point arithmetic before exporting cents.
Here is a small Node.js workflow that keeps those cases separate and produces a CSV suitable for a spreadsheet or a historical-data pipeline.
Start with a fixed historical month
The savings-bond-value-files source includes a dependency-free parser, an API client, a CLI and a recorded official response. Use Node.js 22.12 or newer:
git clone https://github.com/jiankn/savings-bond-value-files.git cd savings-bond-value-files npm test node bin/cli.mjs --period 2023-05 --format csv > values.csv The CLI fetches that redemption period from Treasury. It checks pagination metadata, the number of returned rows, duplicate period/series/year keys and whether every row belongs to the requested month. An unavailable month fails explicitly; the client does not generate an estimate.
For a reproducible conversion without a network request, use the recorded API response:
node bin/cli.mjs --input tests/fixtures/treasury-2023-05.json --format csv > values.csv The fixture's retrieval URL, timestamp and SHA-256 are stored alongside it. A local partial extract is also accepted, so successful offline conversion does not certify that every issue year is present.
Keep the three cell states
The parser maps the official amount strings as follows:
| Input | JSON amount | CSV amount cell |
|---|---|---|
"null" or JSON null | null | empty |
"0.00" | 0 | 0 |
"64.00" | 6400 | 6400 |
Avoid expressions such as Number(raw) || null: zero disappears into the missing-value case. The parser also rejects malformed amounts instead of coercing empty strings or silently accepting scientific notation.
Decimal conversion splits the string and uses integer arithmetic. The public helper can be used separately:
import { amountToCents } from './src/index.mjs'; console.log(amountToCents('0.29')); // 29 console.log(amountToCents('0.00')); // 0 console.log(amountToCents('null')); // null These are parser-format examples, not quoted bond values.
Export from JavaScript
Create export-values.mjs in the checkout's root:
import { writeFile } from 'node:fs/promises'; import { fetchValuePeriod, lookupUnitValue, toCsv } from './src/index.mjs'; const table = await fetchValuePeriod('2023-05'); console.log({ period: table.period, unitValueCents: lookupUnitValue(table, 'I', '2002-03'), sourceUrl: table.sourceUrl, retrievedAt: table.retrievedAt, }); await writeFile('values.csv', toCsv([table])); Run it with node export-values.mjs. The historical example returns 6400 cents. The test suite checks that cell against the recorded Treasury response and verifies all 1,368 amount fields in the fixture.
The CSV columns are:
redemption_period,series,issue_month,unit_value_cents,denomination_cents The Treasury series codes N and S become EE and SN. Each output amount remains a value per $25 face value in the official file, with denomination_cents set to 2500. It is not an arbitrary electronic purchase amount or a calculation of accrued interest.
Where this adapter stops
This tool retrieves and reshapes public data. It does not calculate taxes, current interest rates, early-redemption penalties or electronic-bond scaling. Those are separate financial calculations, not CSV-formatting steps.
For the individual-bond interface, Savings Bond Calculator handles the browser workflow; its methodology explains the data sources and calculation limitations. Project disclosure: this parser is maintained alongside that website.
Not affiliated with the U.S. Department of the Treasury or TreasuryDirect. For information only — confirm the value with TreasuryDirect before cashing a bond. Not financial or tax advice.

