Create an OFX file
CSV to OFX converter
Turn a bank or card CSV into an OFX file using the account details and balances you enter, with a review report. Runs in your browser.
This tool processes your file and entries in this browser tab, without uploading or saving them.
UTF-8 .csv or .txt, up to 5 MB. File contents never leave this tool.
Privacy and clearing your input
This tool does not send your file contents to a server or save them in browser storage. Use Clear or reload to clear the active input. Navigating away and Back may restore uncleared contents. Download and print actions, where offered, create copies only when you choose them. Your browser manages temporary memory and any separate print window. The PDF converter has its own upload workflow.
Plain OFX 2.2 XML only. You supply the account and a real closing balance. This tool was not tested in live Quicken, QuickBooks or any bank-specific import.
CSV read: 0 data records.
Format: needs your review.
Export: not created
Turn one account's CSV into a plain OFX file, with a preview and a read-back check before you download it. You supply the account details and real closing ledger balance. No signup, bank connection or upload is needed.
By AnyStatement
Published , 6 min read
If your bank already provides OFX, use that first
A bank-native export can carry transaction identifiers that a CSV does not have. This tool is for a CSV you already have and an application whose documented import accepts plain OFX. Check the destination's native CSV import before adding a conversion step.
This is OFX 2.2 XML in UTF-8, without a byte-order mark. It is not QBO or QFX, and renaming the extension does not make it either. No Intuit institution ID, FI organization or financial-institution identity is invented. The file is converter-created, not bank-issued.
Quicken says it does not support QFX files created by third-party conversion software. Its Web Connect troubleshooting page was updated April 29, 2025. This tool was not tested in live Quicken, QuickBooks or any bank-specific import. A successful read-back is not a promise that an application will accept the file.
Map posted rows, then confirm the account
Map the posted date, description and one signed amount column, or separate debit and credit columns. Choose the source date order, number separators and sign convention explicitly. Optional mappings keep the original transaction date, payee, reference and a source transaction ID separate. The description becomes MEMO when it differs from NAME. A reference is not silently promoted to a transaction ID or check number.
Output amounts use the account holder's perspective: money in is positive, money out negative. For credit cards, a purchase is negative and a payment or refund positive. A card balance owed is negative, not a positive liability balance. Read the card sign guide if the source uses the opposite convention.
Banking supports the US checking and savings profile, with a nine-digit BANKID that you supply from your own bank. Other banking-country profiles and BRANCHID are not generated. Card exports use the credit-card aggregate. Your stable account ID is required; do not reuse the same last-four label for two different accounts. The institution label is used only to distinguish synthetic IDs, not to claim bank participation.
Choose one currency: USD, CAD, EUR, GBP, AUD, NZD or CHF. These are the named two-decimal currencies supported here, not a claim about every currency or importer. Mapped currency values must match your choice exactly. You also confirm that unmapped columns do not hide a second account, currency or pending transaction.
What the generated transaction IDs mean
If you map a source ID column, its nonblank unique values become FITIDs without hashing or renaming. Duplicate source IDs stop the export. IDs may contain up to 255 characters under this subset, although the OFX specification recommends 32 or fewer for performance. The tool does not establish that an ID came from a bank.
Without source IDs, each row gets the first 32 hexadecimal characters of SHA-256. The canonical tuple contains the institution label, bank ID (empty for cards), account ID, account type, currency, posted date, original date, exact signed amount, original payee, original memo and reference (before any accepted text changes). Each value is prefixed by its UTF-8 byte length and a colon. That tuple and its occurrence number, starting at 1, are length-prefixed again before hashing.
Unchanged inputs and account identity produce unchanged IDs; a fixed generation timestamp also produces identical file bytes. Reordering distinguishable rows does not change their IDs. Identical legitimate rows remain separate because each occurrence gets a different ID. But a partial export containing one of two indistinguishable rows cannot tell us which occurrence it was. Do not rely on these synthetic IDs for automatic overlap deduplication or safe repeated imports.
A real closing balance is required, not inferred
Enter the closing ledger balance and its as-of date, which must match the statement end. The tool never substitutes zero for a missing balance, guesses an opening balance or creates a balancing transaction. Every supplied posted date must fall inside your selected range; out-of-range rows stop export rather than disappearing.
If you supply an independent opening balance immediately before the range starts, the tool checks opening plus all posted amounts against closing. A mismatch stops export. Without it, the report says arithmetic was not independently checked. Computing an opening from the closing and then adding the same rows back would only prove the calculation was circular. Even matching arithmetic does not prove transaction completeness or document authenticity.
The fictional Load example starts at 1,000.00. Salary of 1,200.00, groceries of -42.50, a 19.99 refund and utilities of -107.35 sum to 1,070.14. Closing is 2,070.14 on June 30, 2026. All four rows survive the OFX read-back. The example's account and routing identifiers are fictional and must not be used for your real import.
Review text changes before downloading
NAME is limited to 32 characters and MEMO to 255. Whitespace normalization and any proposed truncation are shown beside the original text and require your confirmation. You can edit the source instead. References with surrounding whitespace or over 32 characters and unsupported XML characters block export rather than being dropped. XML-special characters such as ampersands and angle brackets are escaped without changing their text value.
Amounts use exact integer cents, never floating-point rounding. Negative zero becomes 0.00; excess decimal precision is rejected. The amount field is limited to 32 characters, including its sign and decimal point. Transaction types are CREDIT, DEBIT or OTHER according to the signed amount, not guesses about the merchant.
Transaction dates are written at noon GMT, with a separate original date when mapped and different from the posted date. OFX treats the transaction range end as exclusive, so DTEND is noon GMT on the day after your inclusive statement end. The closing balance keeps its supplied as-of date. This does not guarantee that every importing application or timezone will display the same calendar day. Use date-only input; resolve timestamps, CR/DR amount suffixes, repeated headers, subtotal rows and blank records before exporting.
The limit is 5,000,000 UTF-8 input bytes and 10,000 data rows. Comma, semicolon, tab and pipe separators are supported. One account, one currency and posted bank or card transactions only: no investments, loans, pending items, correction records, split transactions, QBO/QFX identity fields, attachments or automatic categorization. Unmapped CSV columns are not carried into OFX.
What was checked, and what stays on your device
Each export is read back by a separate, narrow reader in this tool. It compares transaction count, every supported transaction field, account metadata and the supplied balance with the prepared values. This reader handles the tool's own output, not every valid OFX file and not a complete OFX schema validation. To inspect an existing file, use the bank file inspector.
Synthetic fixture checks compare transaction values with the repository's Python exporter and the independent ofxtools parser. We also converted 360 randomized CSV files and compared every supported field in all 4,608 transactions with independently calculated expectations and ofxtools. Cases include card signs, negative zero, large amounts, XML-special characters and same-day duplicates. These are file-structure and value checks, not live destination imports.
We opened the OFX 2.2 specification, dated November 26, 2017, and Quicken's support page on October 18, 2026. Sections 3.2.3, 3.2.6-3.2.7 and 11.4.2-11.4.4 describe the ID, memo, exclusive end date and banking/card structures behind this subset. Version 2.2 is the deliberate target, not a claim to support the newest or entire OFX standard.
Your file and the values you enter are processed in this browser tab. They are not uploaded or sent to analytics. We do not save them between visits. Downloads you choose to save remain on your device. Use Clear to remove active inputs and results; Back navigation may restore uncleared state. Clear is not a secure memory wipe.
The OFX contains account identifiers and full transaction data. The separate text report withholds account identifiers and transaction text, but still contains financial totals and dates. Both are new files, not changes to your source CSV. Inspect them before sharing or importing.
If the only source is a PDF
Ask the bank for a native financial file first, or use an import option already included in your bookkeeping app. For PDF-only history, AnyStatement can extract reviewable rows in a separate upload workflow. 3 pages a day without an account or card. The free allowance is shared per network and resets at midnight UTC. Conversion is a separate upload; this tool does not send its contents there. Check the extracted dates, signs and balances against the statement before using those rows here.