npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

is-valid-tfn

v0.0.4

Published

Check if a value is a valid Australian Tax File Number (TFN)

Readme

is-valid-tfn

is-valid-tfn is a small TypeScript package that exports isValidTFN(value: unknown): boolean and checks whether a value matches the best publicly supported validation rules for an Australian Tax File Number (TFN).

This repository started as a fork/template of wojtekmaj/is-valid-abn. The original project structure and MIT license were retained as attribution, but the TFN research, implementation, tests, package metadata, and documentation were rewritten for this repository.

API

export default function isValidTFN(value: unknown): boolean;

Returns true when the input matches this package's supported TFN formatting and checksum rules. Returns false otherwise.

Behavior Summary

  • Accepts unknown input and returns false for null, undefined, empty strings, and whitespace-only strings.
  • Accepts string, number, bigint, and other values that produce a candidate through String(value).
  • Accepts ASCII digits with optional spaces.
  • Rejects alphabetic characters and unsupported punctuation such as hyphens.
  • Rejects malformed lengths other than 8 or 9 digits after removing spaces.
  • Validates 9-digit TFNs with the public modulo-11 rule corroborated by multiple secondary technical sources.
  • Validates legacy 8-digit TFNs using the best public secondary evidence available.
  • Rejects ATO substitute/reporting codes such as 000000000, 111111111, 333333333, 444444444, and 987654321.
  • Only checks mathematical validity. It does not prove that a TFN was actually issued to a person or entity.

Research Methodology

I used the following source order:

  1. Official ATO developer material.
  2. Other official government references.
  3. Independent technical references and library implementations.
  4. Stack Overflow only as supporting context.

The public ATO developer specification was the anchor source. It clearly distinguishes a valid TFN from substitute reporting codes and confirms that a TFN checksum algorithm exists, but it does not publish the exact checksum weights in the public document. Because of that gap, the exact weights had to come from corroborating secondary sources.

The public evidence is strongest for 9-digit TFNs. Legacy 8-digit TFNs are the main area of ambiguity. Official sources confirm that 8-digit TFNs exist and refer to an "8 or 9 digit TFN algorithm", but the current public ATO material does not publish the legacy weights. I therefore compared independent secondary implementations and documented the conflict instead of hiding it.

Evidence Table

| Claim | Evidence summary | Source link | Source type | Accessed date | | --- | --- | --- | --- | --- | | Valid TFNs and substitute reporting codes are different concepts | The ATO TFN declaration reporting spec says the payee TFN field must contain a valid TFN, but when a TFN is missing or invalid it requires substitute codes such as 000000000, 111111111, 333333333, 444444444, and 987654321. | ATO TFN declaration reporting specification v4.0.3 | official | 2026-03-17 | | Alphabetic TFN input is not a valid TFN | The same ATO spec says 987654321 must be lodged when alphabetic characters appear in a quoted TFN or the quoted TFN cannot fit in the field. | ATO TFN declaration reporting specification v4.0.3 | official | 2026-03-17 | | The public ATO spec confirms an algorithm exists but does not publish the exact public weights | Section 9 says the TFN algorithm is available through Online services for DSPs or by request to the DPO, rather than printing the algorithm directly in the public spec. | ATO TFN declaration reporting specification v4.0.3 | official | 2026-03-17 | | TFNs can be 8 digits or 9 digits | The public ATO spec says the WPN algorithm uses the "8 or 9 digit TFN algorithm" after removing leading zeros. The ANAO audit describes a TFN as an 8- or 9-digit number whose last digit is generated from a 7- or 8-digit base. | ATO TFN declaration reporting specification v4.0.3, ANAO audit | official | 2026-03-17 | | Spaces are a reasonable formatting tolerance | The OECD Australia TIN note says the TFN is stored as an 8- or 9-digit string and may be displayed in groups of three digits. Technical libraries such as python-stdnum also accept spaces. | OECD Australia TIN note, python-stdnum AU TFN source | official, secondary | 2026-03-17 | | The 9-digit checksum rule is a modulo-11 weighted sum | Clearwater documents weights [1, 4, 3, 7, 5, 8, 6, 9, 10] and a modulo-11 check. python-stdnum independently uses the same 9-digit weights. | Clearwater TFN reference, python-stdnum AU TFN source | secondary | 2026-03-17 | | Best-available public evidence for legacy 8-digit TFNs supports a separate weight set | A Stack Overflow answer cites the older ATO obtainTFNalgorithm page and gives 8-digit weights [10, 7, 8, 4, 6, 3, 5, 1]. The tfn-validator package independently uses the same 8-digit weights. | Stack Overflow discussion, tfn-validator package | community, secondary | 2026-03-17 | | Secondary sources conflict on legacy 8-digit handling | python-stdnum accepts 8-digit TFNs but reuses the 9-digit weight prefix, which conflicts with sources that distinguish separate 8- and 9-digit algorithms. | python-stdnum AU TFN source, tfn-validator package | secondary | 2026-03-17 |

Decision Log

Why 8-digit TFNs are supported

Official sources say TFNs can be 8 digits or 9 digits, but the public ATO document does not print the legacy weights. I chose to support legacy 8-digit TFNs because:

  • the ATO wording implies distinct 8- and 9-digit algorithms rather than a single public 9-digit rule,
  • the ANAO audit independently confirms that 8-digit TFNs exist and include a check digit,
  • a Stack Overflow answer citing the older ATO obtainTFNalgorithm page and the tfn-validator package agree on the 8-digit weights [10, 7, 8, 4, 6, 3, 5, 1].

I did not follow python-stdnum for legacy 8-digit TFNs because it reuses the 9-digit weights on 8-digit input, which conflicts with the sources above and with the official wording that refers to an "8 or 9 digit TFN algorithm". This is therefore a best-available-evidence decision, not a direct quotation of a current public ATO checksum table.

Why spaces are accepted

The OECD Australia TIN note says TFNs may be displayed in groups of three digits, and multiple technical implementations accept spaced input. I therefore accept spaces as a formatting convenience.

This package does not strip arbitrary punctuation. In particular, it rejects hyphens and alphabetic characters rather than trying to guess what the user meant.

Why substitute reporting codes are rejected

The public ATO specification explicitly says those codes are used in place of a TFN in reporting contexts when the payee has not quoted one, is applying for one, is exempt, or provided invalid alphabetic content. They are valid reporting substitutes in that context, but they are not valid TFNs.

Because the exported API is isValidTFN(...), this package rejects substitute codes.

Why alphabetic characters are rejected

The ATO reporting specification instructs payers to use 987654321 when alphabetic characters appear in the quoted TFN. That is strong official evidence that alphabetic input is not a valid TFN and should not be normalized into one.

Whether the public official docs fully disclose the checksum weights

No. The current public ATO developer specification confirms that the algorithm exists and recommends using it in software, but it does not print the exact checksum weights in the public document. Exact weights therefore require secondary corroboration.

Why the chosen 9-digit rule is still strong

Clearwater and python-stdnum agree on the familiar 9-digit weights [1, 4, 3, 7, 5, 8, 6, 9, 10].

The tfn-validator package presents a different 9-digit weight vector, [10, 7, 8, 4, 6, 3, 5, 2, 1], but that vector is just the Clearwater vector multiplied by 10 modulo 11. Because multiplying every weight by a non-zero constant modulo 11 does not change which sums are divisible by 11, both forms define the same 9-digit validity test.

Limitations

  • Passing this validator means the input matches a checksum and formatting rule. It does not prove that the TFN was ever issued.
  • This package is not legal, accounting, or tax advice.
  • The current public ATO developer documents do not publish the exact checksum weights directly.
  • Legacy 8-digit support is based on best available public evidence, not on a currently public ATO checksum table.
  • Secondary sources conflict on 8-digit handling. That conflict is documented above.
  • This package accepts spaces but intentionally does not accept every punctuation style that some third-party libraries strip.

Usage Example

import isValidTFN from 'is-valid-tfn';

isValidTFN('876543210'); // true
isValidTFN('876 543 210'); // true
isValidTFN('12345677'); // true (legacy 8-digit support)

isValidTFN('987654321'); // false, substitute reporting code
isValidTFN('876-543-210'); // false, hyphens are not accepted
isValidTFN('87654A3210'); // false, alphabetic characters are rejected

The examples above are checksum-valid examples only. They should not be treated as proof that a TFN has actually been issued.

Development

This repository uses mise for tool management and task execution, and it uses Microsoft's native TypeScript preview (tsgo) for typechecking and builds.

mise install
mise run install
mise run test
mise run build

Useful tasks:

  • mise run format
  • mise run lint
  • mise run typecheck
  • mise run unit
  • mise run test
  • mise run build

For VS Code, this repository includes workspace settings that recommend the official TypeScript (Native Preview) extension and enable js/ts.experimental.useTsgo so the editor uses the same native language service as the command line.

Verification Notes

The following commands were run after implementation:

  • mise run install Result: installed the local Node dependencies with pnpm.
  • mise run test Result: biome check, tsgo, and vitest run all passed. Vitest reported 1 test file and 11 passing tests.
  • mise run build Result: tsgo --project tsconfig.build.json built the package into dist/ successfully.

Source Links