Skip to content
Quasar Tools Logo

How to Create an INI File

How to create an INI file from scratch — syntax rules, sections, keys, values, comments, encoding, and when to use INI vs TOML or YAML for configuration.

DH
Tutorials & How-Tos11 min read2,550 words

The INI file format has been used to store application settings since the early days of Windows, and it remains in active use across Python projects, PHP configurations, MySQL, Git, and dozens of other tools. Creating one correctly requires understanding a handful of syntax rules, knowing where parsers vary in their behaviour, and choosing the right format for your use case. This guide covers all of it — from the first line to validation.

1983Format originMicrosoft Windows 1.x era
0Special librariesPlain text, any editor works
2-levelMax native depthSections + key-value pairs

What is an INI file?

An INI file is a plain text configuration file that stores settings as key-value pairs, optionally grouped into named sections. The name comes from "initialisation" — INI files were used to initialise Windows applications with their settings before the Windows Registry existed. The format never had a formal specification, but a de-facto standard emerged from widespread use.

Where INI files are used today

  • Python packaging — `setup.cfg`, `tox.ini`, `pytest.ini`, `mypy.ini`, `.flake8`
  • PHP runtime — `php.ini` controls PHP interpreter settings globally
  • MySQL / MariaDB — `my.ini` (Windows) and `my.cnf` (Unix) configure the database server
  • Git — `.gitconfig` and `.git/config` use an INI-like format for repository and user settings
  • Wine — `wine.inf` configures the Windows compatibility layer on Linux and macOS
  • Windows applications — thousands of legacy and modern desktop apps store preferences in `.ini` files in the AppData folder

INI vs the Windows Registry

Microsoft moved Windows application settings to the Registry in the early 1990s for reasons of performance and centralised management. However, many developers continue to prefer INI files for portability — an INI file can be inspected and edited with any text editor, committed to version control, and copied between machines without any export/import tooling. The Registry cannot.

Note

Because INI has no formal specification, different parsers implement slightly different rules for edge cases: whether # is a valid comment character, whether inline comments are allowed, and how duplicate keys are handled. Python's `configparser`, Windows' `GetPrivateProfileString`, and PHP's `parse_ini_file()` all diverge on at least one of these points.

INI file syntax rules

Despite the lack of a formal spec, INI syntax follows consistent conventions across virtually all parsers. These are the rules you can rely on regardless of what reads your file.

An INI file is the simplest possible configuration format: sections in brackets, key-value pairs beneath them, and semicolons for comments. Everything else is parser-specific.

Informal INI format consensus

Universal rules

  • One key-value pair per line — `key = value` or `key=value`; the space around `=` is optional but consistent spacing is readable
  • Section headers — `[SectionName]` on its own line; no trailing content after the closing bracket
  • Comment lines — start with `;` for maximum compatibility; `#` is supported by some parsers (Python `configparser`, Linux tools) but not Windows native APIs
  • Blank lines — ignored by all parsers; use them freely to separate logical groups within a section
  • No nesting — INI is flat: sections contain key-value pairs, not other sections
  • String values — all values are strings unless the parser converts them; `count = 5` is the string "5" to most parsers

What the parser sees

The parser builds a two-level map: section name → key → value. If a file has no section headers, values are in an implicit "default" section — Python's `configparser` calls this `DEFAULT`. Whether the parser merges the default section with named sections varies. Keys and section names are almost universally treated as case-insensitive by convention, though this is not guaranteed by all implementations.

Tip

Always validate your INI file with the [INI Validator](/tools/data/validators/ini-validator) before deploying it. Common silent mistakes — a typo in a section name, a duplicate key, or a value on the same line as a section header — will pass a visual review but cause the parser to silently use the wrong value.

Creating your first INI file

Creating an INI file takes fewer than five steps. The only tool required is a plain text editor — any editor that saves as UTF-8 or ASCII without a byte order mark (BOM) works correctly.

1

Create a new text file with the .ini extension

Open your text editor (VS Code, Notepad, nano, vim — any of them work) and create a new file. Save it with the `.ini` extension before writing any content so the editor applies INI syntax highlighting if available. On Windows, make sure "Save as type" is set to "All files" in Notepad to avoid the file being saved as `config.ini.txt` instead of `config.ini`.

2

Add your first section header

Write your first section name in square brackets on its own line. Section names are descriptive labels — `[database]`, `[server]`, `[logging]` are conventional choices. You can also start writing key-value pairs immediately without any section header if your config is simple enough to not need grouping.

3

Add key-value pairs under each section

Below the section header, write one `key = value` pair per line. Keys should be lowercase with underscores (snake_case) for maximum cross-parser compatibility. Values can include spaces, punctuation, and most special characters. Do not wrap values in quotes — quotes are treated as literal characters by most parsers, not as string delimiters.

4

Add comments to document non-obvious values

Start comment lines with a semicolon (`;`). Comments must be on their own dedicated line — placing a comment after a value on the same line (`host = localhost ; primary DB`) is not reliably supported by all parsers and may include the comment text in the value. If you need inline notes, put them on the preceding line as a standalone comment.

5

Validate the finished file

Paste your completed INI file into the INI Validator to check for syntax errors, duplicate section names, and format compliance. The validator reports issues with line numbers so you can fix them before putting the file into production. If you need consistent formatting, run it through the INI Formatter first.

INI Validator

Check any INI or CFG file for syntax errors, duplicate sections, and format compliance — line-level error reports with no uploads required.

Open tool

Sections, keys, and values in depth

The three structural elements of an INI file — sections, keys, and values — have rules and edge cases worth understanding before writing a config that will be read by someone else's parser.

Section naming conventions

Section names go inside square brackets and appear on their own line. They can contain letters, numbers, spaces, and most punctuation — but spaces in section names are poorly supported by some parsers and should be avoided. Use `[DatabaseConfig]` or `[database_config]` rather than `[database config]`. Duplicate section names are either merged or cause an error depending on the parser — treat them as forbidden and validate with the INI Validator to catch duplicates.

Key naming rules

Keys must not contain the `=` sign or a newline. Beyond that, the conventions vary, but the safest practice is to use only lowercase letters, digits, and underscores — the same rules as Python variable names. Avoid hyphens in keys if you plan to read them in Python with `configparser`, since Python returns keys as-is and hyphenated keys cannot be accessed as attributes.

Value types and multiline values

All values in INI files are strings unless your parser explicitly converts them. `enabled = true` is the string "true" — your code must convert it to a boolean. Python's `configparser` provides `getboolean()`, `getint()`, and `getfloat()` methods for this purpose. Multiline values are supported by some parsers (Python's `configparser` treats lines with leading whitespace as continuations of the previous value) but not all — check your parser's documentation before relying on this.


The DEFAULT section

Python's `configparser` treats a section named `[DEFAULT]` (case-insensitive) as a special fallback section. Any key defined in `[DEFAULT]` is available in all other sections as a fallback — if a section does not define a key, the value from `[DEFAULT]` is returned instead. This is a Python-specific behaviour not found in most other parsers. If you are writing INI files for Python specifically, `[DEFAULT]` is a useful way to define shared values without repeating them in every section.

Warning

Do not put sensitive values — passwords, API keys, tokens — in INI files that will be committed to version control. INI files are plain text and trivially readable. Store sensitive values in environment variables instead, and reference them by name in the INI file as a hint: `password = <DB_PASSWORD>` (noting that most INI parsers will treat this as the literal string, not a variable expansion).

Comments and encoding

Comments and character encoding are the two aspects of INI files most likely to cause silent problems when files are shared across different tools, operating systems, or programming languages.

Comment characters: ; vs #

The semicolon (`;`) is the universally supported comment character — it works in Python's `configparser`, Windows native APIs, PHP's `parse_ini_file()`, MySQL, and virtually every other INI parser. The hash (`#`) is supported by Python's `configparser` and most Linux-based parsers but is not supported by Windows' `GetPrivateProfileString()`. If your INI file will only ever be read by Python, either character is safe. For cross-platform files, use `;` exclusively.

Character encoding: UTF-8 vs Windows-1252

Save INI files as UTF-8 without BOM for modern tools. The BOM (byte order mark, the invisible `\uFEFF` character at the start of some UTF-8 files saved by Windows tools) causes problems with parsers that treat it as part of the first key name. Python's `configparser` handles UTF-8 natively since Python 3. If you are writing an INI file for a legacy Windows application that expects Windows-1252 encoding, match what the application expects — mixing encodings is a common source of character corruption in values.

Line endings

INI files work with both Windows (CRLF, `\r\n`) and Unix (LF, `\n`) line endings. Use the line ending convention of your target platform. If you are editing an INI file on Windows for deployment on Linux, configure your text editor to save with LF line endings to avoid the carriage return character appearing in values on Linux parsers. The INI Formatter normalises line endings and spacing in one pass.

Reading INI files in code

Most languages provide a built-in or standard library parser for INI files. Here are the standard approaches for the most common environments.

Python: configparser

Python's `configparser` module is the standard way to read INI files in Python. Import it, create a `ConfigParser()` instance, call `.read()` with your filename, and access values with `config["SectionName"]["key"]` or `config.get("SectionName", "key")`. The `.get()` method accepts a `fallback` argument that returns a default value when the key is missing — useful for optional config values. Use `getboolean()`, `getint()`, and `getfloat()` for typed values rather than casting strings manually.

PHP: parse_ini_file()

PHP provides `parse_ini_file($filename, $process_sections)` as a built-in function. With `$process_sections = true`, the function returns a nested associative array organised by section name. With `false`, it returns a flat array with all keys merged. PHP's parser is strict about certain special characters in unquoted values — values containing =, opening/closing braces, |, &, ~, !, [, ] need to be quoted in the INI file to be parsed correctly.

Node.js and other environments

Node.js has no built-in INI parser, but the `ini` npm package (MIT licence) provides a standard `parse()` and `stringify()` interface. For Java, the `org.ini4j` library is the standard choice. For Go, the `gopkg.in/ini.v1` package is the most widely used option. In each case, the library handles the same two-level section/key structure — the API shapes vary but the underlying format is identical.

Tip

If you need to migrate an INI configuration file to a modern format, the [INI to YAML Converter](/tools/data/converters/ini-to-yaml) converts your INI file to well-structured YAML instantly in your browser. For Rust or Python packaging projects adopting modern tooling, consider TOML — the [TOML Validator](/tools/data/validators/toml-validator) helps you verify the converted result.

INI vs TOML vs YAML

INI is not always the right configuration format. Understanding where it fits — and where TOML or YAML is a better choice — helps you make the right decision for new projects.

FeatureINITOMLYAML
Syntax complexityMinimalModerateHigh
Native type support✗ Strings only✓ Full types✓ Full types
Nested structures✗ Two levels max✓ Inline tables✓ Unlimited depth
Arrays / lists✗ Not standard✓ Native arrays✓ Block sequences
Comments✓ ; and #✓ # only✓ # only
Formal specification✗ No official spec✓ TOML spec✓ YAML 1.2 spec
Best forSimple app configRust, Python pkgDevOps, Kubernetes
ReadabilityVery highHighMedium (indent-sensitive)

When to use INI

INI is the right choice when your configuration is two levels deep (sections and flat key-value pairs), when the target parser already expects INI format (PHP, Python ecosystem, MySQL, Git), and when you want the absolute simplest possible format that any developer can read without prior knowledge. It is not appropriate for configurations that need arrays, nested objects, or typed data.

When to use TOML or YAML instead

Choose TOML when your config needs typed values, arrays, or inline tables and you want a strict specification with predictable parsing. TOML is the format for `pyproject.toml`, `Cargo.toml`, and Hugo's configuration files. Choose YAML when you need deeply nested structures or are working in an ecosystem where YAML is already standard — Kubernetes, GitHub Actions, Docker Compose, and Ansible are all YAML-first environments.

Key takeaways

  • An INI file is a plain text configuration file with named sections in `[brackets]` and `key = value` pairs beneath them.
  • Use `;` for comments — not `#` — for maximum compatibility across Windows, PHP, Python, and other INI parsers.
  • Save INI files as UTF-8 without BOM; avoid inline comments (after a value on the same line) as they are not universally supported.
  • All INI values are strings unless your parser explicitly converts them — use `getboolean()`, `getint()`, and `getfloat()` in Python.
  • Never store passwords or API keys in INI files committed to version control — use environment variables for sensitive values.
  • Validate with the INI Validator before deployment to catch syntax errors, duplicate sections, and format problems.
  • Use TOML for configs needing typed values and arrays; use YAML for deeply nested structures — INI is ideal only for simple two-level configurations.

Frequently Asked Questions

An INI file is a plain text configuration file that stores settings as key-value pairs, optionally organised into named sections using square bracket headers. The format originated with early Microsoft Windows to store application settings, and remains in use in Python projects (setup.cfg, tox.ini), PHP (php.ini), MySQL (my.ini), Git (.gitconfig), Wine, and many other tools. INI files are human-readable, require no special parser library, and edit cleanly with any text editor.

Create a new plain text file in any text editor and save it with a .ini extension. Add named sections using square brackets — [SectionName] — and list key = value pairs beneath each section, one per line. Add comments by starting a line with a semicolon (;). The file requires no special opening declaration or closing tag. Once written, validate it with the INI Validator to catch any syntax errors before putting it into use.

The basic rules are: section names go in square brackets on their own line ([SectionName]); key-value pairs use the format key = value, with one pair per line; comments start with ; on a standalone line; blank lines are ignored; keys and section names are typically case-insensitive but this depends on the parser. There is no official INI standard — each application that reads INI files may support slight variations of this syntax.

The .ini extension is the conventional choice for INI format files. Some applications use .cfg (configuration) or .conf — both are plain INI-format files with different extensions. Python projects commonly use setup.cfg and tox.ini. MySQL uses my.ini on Windows and my.cnf on Unix. The extension does not affect the format — the parser reads the file the same way regardless of the extension name.

Yes. Lines starting with a semicolon (;) are treated as comments by almost all INI parsers. Some parsers also support lines starting with # as comments — Python's configparser supports both, while Windows' GetPrivateProfileString only supports ;. For maximum compatibility across different parsers and operating systems, use ; for all comment lines. Inline comments (placed after a value on the same line) are not universally supported and should be avoided.

Python's standard library includes the configparser module specifically for reading INI-format files. Import it with `import configparser`, create a parser with `config = configparser.ConfigParser()`, and load your file with `config.read("config.ini")`. Access values with `config["SectionName"]["key"]`. By default, configparser converts all keys to lowercase and treats section names as case-sensitive. The module handles multi-line values, % interpolation, and fallback values out of the box.

INI is the simplest: flat sections with string key-value pairs and no native type support. TOML adds types (integers, booleans, arrays, inline tables) with a strict spec and is the format of choice for Rust (Cargo.toml) and Python packaging (pyproject.toml). YAML is the most expressive but also the most complex, supporting nested structures, anchors, and aliases — common in Kubernetes, GitHub Actions, and Docker Compose. For simple two-level configuration, INI is readable and sufficient. For anything with arrays or nested structure, TOML or YAML is more appropriate.

It depends entirely on the parser. Python's configparser converts all keys to lowercase by default, making them case-insensitive in practice. Windows' native INI functions are also case-insensitive. However, there is no universal standard — some parsers treat keys as case-sensitive. To avoid ambiguity, always write keys in a consistent case throughout your file. Lowercase with underscores (snake_case) is the most common convention and the safest choice for cross-parser compatibility.

ShareXLinkedIn

Related articles