ONNXMLTools: converting Keras, Core ML, XGBoost and H2O models to ONNX
ONNXMLTools enables conversion of models to ONNX
At a glance
- What is it?
- ONNXMLTools is a Python package that turns models from nine different toolkits into ONNX graphs. The converters are unevenly maintained, and the opset behaviour surprises people who expect target_opset to be exact.
- Who is it for?
- Adopt ONNXMLTools if you already have a trained model in one of its nine supported toolkits and need an ONNX artifact for an ONNX Runtime deployment. Do not adopt it if your model lives in PyTorch, which ships its own exporter, or if you need a converter the README marks as experimental, such as Spark ML.
- Can I use it commercially?
- Yes. Apache-2.0 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 29 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.
Editorial analysis
What ONNXMLTools converts, and who ends up using it
A trained model is only useful in production if the serving stack can load it. ONNXMLTools exists to close that gap for people whose model was trained somewhere that does not speak ONNX natively. The README lists nine supported sources: Tensorflow, scikit-learn, Apple Core ML, Spark ML, LightGBM, libsvm, XGBoost, H2O and CatBoost. PyTorch is named only to point elsewhere, since it ships a built-in exporter.
The audience is narrow and practical. You have a gradient boosted model pickled from XGBoost or LightGBM, or a Core ML artifact from an iOS pipeline, and you want one file that ONNX Runtime can execute. ONNXMLTools is the translation layer, not a training library and not a runtime.
The package metadata in pyproject.toml classifies it as Development Status 4 - Beta, which is worth reading literally. Several converters are wrappers rather than independent implementations: the README states that Tensorflow support is a wrapper of the tf2onnx converter and scikit-learn support is a wrapper of skl2onnx. That matters when you file a bug, because the fix may live in a different repository.
How the conversion pipeline actually works
The core mechanism is per-operator translation. The README describes it directly: the converter converts each operator to the ONNX format individually and finds the corresponding opset version that it was most recently updated in. Once every operator is done, the resulting model carries the maximum opset among its operators.
That design produces a behaviour people misread as a bug. If you request target_opset=8 for a graph containing only Abs and Add, and Abs was last updated in opset 6 while Add was last updated in opset 7, the output reports opset 7. The README calls this intended and says it was defined this way to ensure backwards compatibility. The practical consequence is that target_opset is a ceiling, not a target. If your runtime requires an exact opset, you cannot rely on the parameter to produce it.
You can inspect the outcome in one line, which the README gives as onnx_model.opset_import[0].version. Netron is offered as the visual alternative for the same check.
Installing ONNXMLTools and running a first Core ML conversion
The README gives two install paths. The released package comes from PyPI, and a source install pulls straight from the repository.
pip install onnxmltoolspip install git+https://github.com/onnx/onnxmltoolsThere is a caveat attached to the second one. The README states that if you install onnxmltools from source code, you must set the environment variable ONNX_ML=1 before installing the onnx package. Skipping that step is a common source of confusing import failures.
Dependencies are light at the base layer: ONNX, NumPy and ProtoBuf, with skl2onnx pinned at 1.4.9 or higher in pyproject.toml. The toolkit you are converting from is your problem, not the package's. Converting a Core ML model means having CoreMLTools installed, and the README caps that at version 3.1 or lower.
The README's Core ML example loads a spec, converts it, and saves the protobuf. Note that the second argument is a model name, not a path.
import onnxmltools
import coremltools
coreml_model = coremltools.utils.load_spec('example.mlmodel')
onnx_model = onnxmltools.convert_coreml(coreml_model, 'Example Model')
onnxmltools.utils.save_model(onnx_model, 'example.onnx')After this runs you should have example.onnx on disk. The H2O path is simpler still, taking a MOJO zip directly and requiring only that the file exists locally.
import onnxmltools
onnx_model = onnxmltools.convert_h2o('/path/to/h2o/gbm_mojo.zip')
onnxmltools.utils.save_model(onnx_model, 'h2o_gbm.onnx')For Keras, the README shows convert_keras with an optional target_opset argument, and its example passes target_opset=7 for ONNX release version 1.2.
The Core ML and Spark ML converters are the weak points
Not every listed toolkit gets equal treatment, and the README is unusually candid about it. Spark ML is labelled experimental in the supported-toolkit list. That is a warning, not a formality: an experimental converter in a package classified as Beta means you should expect gaps in operator coverage and verify your specific pipeline before planning around it.
Core ML has a different problem, a version ceiling. The dependency list specifies CoreMLTools version 3.1 or lower. Anyone on a current Core ML toolchain is outside the tested configuration, and the README does not describe what happens above that line. This is the clearest case where ONNXMLTools may simply be the wrong tool, not because the converter is bad but because its supported input format has moved on.
The third limitation is structural. Because Tensorflow and scikit-learn are wrappers, a conversion failure in those paths may not be fixable here. You are debugging a thin layer over tf2onnx or skl2onnx, and the relevant issue tracker may be a different project entirely. The README does not document a rollback path or a way to fall back to the underlying converter from within onnxmltools.
ONNXMLTools against skl2onnx and tf2onnx directly
The honest comparison is not against a rival product but against the upstream converters ONNXMLTools wraps. For a scikit-learn pipeline, skl2onnx is the actual implementation. Installing it directly removes one layer of indirection and gives you its own API, its own documentation and its own release cadence. The same applies to tf2onnx for Tensorflow graphs.
What ONNXMLTools adds is a single entry point across many toolkits. If your team converts XGBoost, LightGBM and H2O models in the same codebase, having convert_xgboost, convert_lightgbm and convert_h2o behind one import is a real reduction in surface area. The package also pins skl2onnx as a dependency, so a plain pip install onnxmltools brings the scikit-learn converter along anyway.
The trade-off is version coupling. When you depend on ONNXMLTools for a scikit-learn conversion, you inherit its skl2onnx pin and its release schedule. Going direct means you track upstream yourself but get fixes the moment they land there.
Maintenance, licensing and what an upgrade costs
The repository is not archived, and the last push was on 2026-09-01. The most recent release listed is 1.16.0 from 2026-01-30, following v1.15.0 on 2026-01-14. So the project is being touched, but releases are not frequent, and the gap between the January release and the September push is worth noting if you need a fix shipped as a versioned artifact rather than a commit.
Licensing is straightforward. The LICENSE file is Apache-2.0, pyproject.toml declares license = "Apache-2.0", and the README source carries an SPDX-License-Identifier: Apache-2.0 header. Apache-2.0 is permissive and includes a patent grant, which is generally the reason projects in this space choose it over MIT. That is a description of the licence, not legal advice; if your organisation has a policy on patent clauses, run it past whoever owns that policy.
Upgrade cost is dominated by the ONNX opset, not by the package version. Because the emitted opset is the maximum among the operators in your graph, moving to a newer onnxmltools can shift the opset your model reports, and that is what your inference runtime has to accept. The pyproject.toml also sets requires-python = ">=3.9" and lists classifiers through Python 3.13, while the README's own testing note says Python 3.7+. Those two statements disagree, and the pyproject.toml is the one that governs installation.
Editorial conclusion
Adopt ONNXMLTools if you already have a trained model in one of its nine supported toolkits and need an ONNX artifact for an ONNX Runtime deployment. Do not adopt it if your model lives in PyTorch, which ships its own exporter, or if you need a converter the README marks as experimental, such as Spark ML. Before committing, verify two things: which opset your converted graph actually reports via onnx_model.opset_import[0].version, and whether your Core ML toolchain is version 3.1 or lower, since the README caps CoreMLTools there. If either check fails, the converter is the wrong layer and you should look at skl2onnx or tf2onnx directly.
Frequently asked questions
What is ONNXMLTools used for?
It converts trained models from toolkits such as Keras, Core ML, XGBoost, LightGBM, H2O and CatBoost into ONNX format, so the resulting file can be run by an ONNX-compatible backend. It is a conversion layer, not a training library or a runtime.
Is ONNXMLTools free to use?
Yes. The repository is licensed under Apache-2.0, declared both in the LICENSE file and in the pyproject.toml license field.
Can I use ONNXMLTools from Python?
It is a Python package, installed with pip install onnxmltools and used through functions such as convert_keras, convert_coreml and convert_h2o. The pyproject.toml requires Python 3.9 or higher.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/onnx-onnxmltools)