Library / SDK
microsoft/Recognizers-Text avatar
microsoft/Recognizers-Text

Microsoft Recognizers-Text: entity recognition for numbers, units and date/time without a model

Microsoft.Recognizers.Text provides recognition and resolution of numbers, units, date/time, etc. in multiple languages (ZH, EN, FR, ES, PT, DE, IT, TR, HI, NL. Partial support for JA, KO, AR, SV). Packages available at: https://www.nuget.org/profiles/Recognizers.Text, https://www.npmjs.com/~recognizers.text

1,794 stars433 forksC#MIT

At a glance

What is it?
Recognizers-Text is a rule-based parser library for numbers, units, date/time and sequence entities across ten fully supported languages, shipped as NuGet, npm, PyPI and Java packages. It is a good fit when you need deterministic, offline extraction of structured values from text, and a poor fit when you need general-purpose NLP.
Who is it for?
Adopt Recognizers-Text if you need deterministic extraction of numbers, units, date/time or sequence entities in one of the fully supported languages and you can pin a package version and accept that the .NET package leads the other platforms.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 152 days ago.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem Recognizers-Text addresses: turning spelled-out values into structured data

A user types "remind me in two and a half hours" or "book a table for cuatro personas a las ocho de la tarde". A general-purpose NLP pipeline will tokenize that and hand you a dependency tree, which is not what you want. You want the string "2.5 hours" or a normalized time value, with a start and end offset pointing back into the original text.

Recognizers-Text is built for exactly that job. The README describes it as providing "recognition and resolution of entities like numbers, units, and date/time; expressed in multiple languages", and lists full support for Chinese, English, French, Spanish, Portuguese, German, Italian, Turkish, Hindi and Dutch, with partial support for Japanese, Korean, Arabic and Swedish. The audience is bot developers, voice-interface teams and anyone normalizing user-entered text before it reaches a database or a scheduling system. Microsoft states that the library powers pre-built entities in LUIS, Power Virtual Agents and the Bot Framework, and base entity types in the Text Analytics Cognitive Service, so the same code path is used inside several Microsoft products.

The design choice worth noting is that this is a rule-based recognizer set, not a trained model. The repository carries a Patterns/ directory alongside Specs/, which is consistent with a grammar-and-regex approach rather than statistical inference. That matters for the trade-offs discussed below.

How the recognizer pipeline works, and why patterns and specs live in separate directories

The repository layout tells you most of the architecture. There is one top-level directory per platform (.NET/, JavaScript/, Python/, Java/) and two shared directories: Patterns/ and Specs/. The README points contributors at the json spec cases, including those temporarily marked as NotSupported, and at translating spec cases that work in English but do not yet exist in a target language. That is the mechanism: behaviour is defined by pattern definitions plus a language-specific resource set, and correctness is pinned by JSON test cases that every platform is expected to satisfy.

At runtime the flow is recognizer then parser. You construct a recognizer for an entity type and a culture, feed it text, and get back a collection of model results. Each result carries the matched text, the start and end offsets, a resolution object with the normalized value, and a type name. The README's support table is effectively the map of available recognizers: Number (cardinal), Ordinal, Percentage, Number Range, Unit (Age, Currency, Dimensions, Temperature), Choice (Boolean), the sequence types (E-mail, GUID, Social, IP Address, Phone Number, URL), and DateTime with its subtypes.

The table also shows where coverage is uneven. Sequence entities are marked G (meaning they come from a generic or shared implementation) rather than a language-specific checkmark, and several cells carry qualifiers such as PA/EO or SO for Japanese, Korean and Swedish. The README states plainly that "Support for English is usually more complete than others" and that the .NET version is primary, with contributions propagating to other platforms "with time". If you are building on the Python or JavaScript package, treat the .NET table as an upper bound on what you will get, not a guarantee.

Installing Recognizers-Text and parsing your first date/time expression

The README points at four distribution channels and gives their URLs. For C#/.NET the NuGet packages are at the Recognizers.Text profile:

bash
https://www.nuget.org/profiles/Recognizers.Text

For JavaScript and TypeScript the npm packages are published under the recognizers-text scope, with the suite package at JavaScript/packages/recognizers-text-suite:

bash
https://www.npmjs.com/~recognizers.text

For Python the PyPI packages are at the recognizers-text user page, which the README marks as alpha:

bash
https://pypi.org/user/recognizers-text/

The Java port is listed as in progress and lives in the Java/ directory. The README does not print an install command or a code sample, so start from the platform directory for your stack. Once you have the package, the shape of a call is recognizer then model then parse: construct a recognizer with a culture code, ask it for the model for the entity type you want, and pass it a string. What comes back is a list of model results, each carrying the matched substring, its offsets in the input, and a resolution value with the normalized date/time or number. Confirm the constructor signatures against the platform directory before wiring the call into production code.

One practical note before you build on this: the DateTime entity is where most integration bugs appear, because resolution depends on the reference moment. The README documents the entity types but does not document a rollback or version-migration procedure, so keep your own fixture set of input strings and expected resolutions and re-run it on every package bump.

Where Recognizers-Text is the wrong tool

This library extracts values that fit its grammars. It does not classify intent, does not do sentiment, does not resolve coreference, and does not answer questions. If your input is a support ticket and you want to know whether the customer is angry, Recognizers-Text has nothing to offer. The README's framing is narrow on purpose: numbers, units, date/time, and a fixed set of sequence patterns.

Language coverage is the second boundary. Ten languages are fully supported and four more are partial. Anything outside that list is not covered, and the README explicitly invites contributions "especially for Japanese, Korean, Arabic, Swedish, and others", which is an admission that those four are incomplete rather than finished. If your product ships in a language not on the table, the library will not help you today.

The third boundary is the platform gap. The README states that .NET is the primary package version and that contributions propagate to the other platforms with time. A recognizer that exists in .NET may be missing or lagging in Python, JavaScript or Java. The support table is presented for .NET and the README notes that support "should propagate" to the others, which is a statement of intent rather than a guarantee. If your stack is Python, verify the specific entity type and culture you need before designing around it.

Finally, ambiguity handling is grammar-driven. When an expression is genuinely ambiguous, the recognizer returns what its patterns produce rather than reasoning about context. That is acceptable for slot filling and risky for anything where a wrong date has real consequences, such as scheduling a payment.

Recognizers-Text compared with spaCy and Duckling

The closest functional alternative in the same problem space is Duckling, the parser behind many chat assistants. The difference in approach is the one that matters most for operations: Duckling runs as a separate HTTP service that you call over the network, while Recognizers-Text is a library you link into your process. A library call has no extra deployment unit, no network hop and no service to keep alive; a service can be shared across language stacks and upgraded independently of your application. If your team is polyglot and wants one parsing endpoint, Duckling's model is easier to operate. If you are a .NET or Node shop that wants parsing inline with no additional infrastructure, the library model is simpler.

Against spaCy, the difference is statistical versus rule-based. spaCy's named entity recognition is a trained model that generalizes to unseen phrasings and produces labels like DATE or MONEY, but it does not resolve "two and a half hours" into a normalized duration, and its accuracy depends on the model and the domain. Recognizers-Text is narrower and deterministic: given the same input and culture, the pattern set produces the same match. It also returns a resolution object, which spaCy's NER does not. For slot filling where you need the normalized value and not just the span, that is the deciding factor.

A third option worth naming is writing your own regexes. For a single entity type in a single language, that is often cheaper than adopting a dependency. Recognizers-Text earns its place when you need several entity types across several cultures, because the Specs/ directory and per-language pattern resources are the part you would otherwise have to build and maintain yourself.

Maintenance, licence and the cost of upgrading between package versions

The repository is not archived, and the last push was on 2026-04-17. The most recent release listed is dotnet-v1.8.12 from 2025-02-13, following dotnet-v1.8.11 in January 2025 and dotnet-v1.8.10 in December 2024. Those release names are .NET-specific, which is consistent with the README's statement that .NET is the primary package version. If you consume the Python or JavaScript package, the release cadence you experience may differ from the .NET one, and the README does not publish a synchronization schedule.

The project is MIT licensed. That is a permissive licence, and the practical implication is that you can use the packages in commercial and closed-source products provided you keep the copyright and permission notice. This is a description of the licence text, not legal advice; route anything unusual through your own counsel. The README also includes a BibTeX entry for academic citation, which is a courtesy rather than a licence term.

Upgrade cost is the part the README does not cover. There is no documented rollback procedure, no compatibility matrix between package versions, and no statement about whether resolution output is considered stable across minor releases. Because the recognizers are pattern-driven, a pattern fix in a new version can change the resolution for an input that previously parsed differently. The mitigation is the same JSON spec approach the project itself uses: keep a fixture file of input strings and expected resolutions, and run it against each new package version before shipping. That file is also the artifact you would hand to a reviewer when a date suddenly resolves to a different day.

Editorial conclusion

Adopt Recognizers-Text if you need deterministic extraction of numbers, units, date/time or sequence entities in one of the fully supported languages and you can pin a package version and accept that the .NET package leads the other platforms. Do not adopt it if you need general-purpose NLP, intent classification or languages outside the supported list, and do not expect the Python package to match .NET feature-for-feature, since the README marks PyPI as alpha and states that .NET is the primary version from which contributions propagate to the other platforms. Before committing, verify two things against your own data: that the entity types you need are marked as supported for your culture in the README table, and that the resolution output for your date/time cases matches what your downstream code expects, since the README does not document rollback or migration behaviour between package versions.

Frequently asked questions

What is Microsoft Recognizers-Text used for?

It recognizes and resolves entities such as numbers, units, percentages, date/time and sequence types like e-mail, URL and phone number, expressed in natural language. The README states that it powers pre-built entities in LUIS, Power Virtual Agents and the Bot Framework, and is also available as standalone packages.

How do I install Recognizers-Text in Python?

The README points Python users at the PyPI user page for recognizers-text, and marks that channel as alpha. The README does not list the individual PyPI package names or a pip command, so check the Python directory in the repository for the current package layout.

Which languages does Recognizers-Text support?

The README lists full support for Chinese, English, French, Spanish, Portuguese, German, Italian, Turkish, Hindi and Dutch, with partial support for Japanese, Korean, Arabic and Swedish. It also notes that English support is usually more complete than the others.

Official sources

  1. Issues
  2. License: MIT
  3. microsoft/Recognizers-Text on GitHub
  4. README
  5. Releases
Community notes

Community notes