Get started
Quickstart
Convert your first spreadsheet or CSV into SQL three ways - in the browser, with the intosql command line, and with the API or one of the SDKs.
This page converts one file three ways: in the browser, on the command line and through the API. Each path uses the same engine, so the SQL and the report are the same.
In the browser
The converter at intosql.com is free and needs no account. Your file is read in the browser and never uploaded.
- Open intosql.com. The converter opens on a sample workbook, already converted.
- Drop your file anywhere on the page, or select Choose your file. It takes
.xlsx,.xlsm,.xls,.xlsb,.ods,.csv,.tsv,.txt,.json,.ndjson, and MySQL or MariaDB dumps as.sqlor.sql.gz. - Pick your database under Your database: PostgreSQL, MySQL, MariaDB, SQLite, SQL Server or Oracle. The SQL is written again for it right away.
- Check the fixes. The summary line reads like
5 rows converted, 8 fixes, none rejected. Each fix has a number, and the same number marks the cell or column it changed on the preview of your file. - Select Download ventas.postgresql.sql, or Copy to put the SQL on the clipboard.
If a column came out wrong, select its header in the preview to rename it, keep it as text or leave it out. The web converter covers every option.
With the command line
The intosql command runs the same engine on your computer. Converting is free.
Install
brew install alfonsobries/intosql/intosqlOr with npm:
npm i -g intosqlTo try it without installing, prefix any command with npx, as in npx intosql convert ventas.xlsx --to postgresql.
Convert
intosql convert ventas.xlsx --to postgresql --output ventas.sqlThe script goes to ventas.sql and a summary goes to standard error:
Converted 4 of 4 rows from ventas.xlsx into ventas for PostgreSQL.
10 fixes made; `intosql inspect ventas.xlsx` lists them.The table is named after the file. --table names it yourself, and --to takes postgresql, mysql, mariadb, sqlite, sql-server or oracle. Without --output, the script goes to standard output.
To see every fix before you convert, run intosql inspect ventas.xlsx. To keep the report, add --report ventas.report.json.
Run the script
The script creates the table and inserts the rows inside one transaction:
-- Written by IntoSQL for PostgreSQL.
SET client_encoding = 'UTF8';
BEGIN;
CREATE TABLE ventas (
no_cliente text NOT NULL,
nombre text NOT NULL,
c_p text NOT NULL,
alta date NOT NULL,
activo boolean NOT NULL,
saldo numeric(6,2)
);Run it with psql:
psql -d tienda -v ON_ERROR_STOP=1 -f ventas.sqlTo skip the script and load the file straight into a database, use intosql load. Loading into SQLite is free; loading into PostgreSQL, MySQL or MariaDB is part of IntoSQL Pro. See Command line for every command and flag.
With the API
The API converts files on IntoSQL's servers, for code that runs without you. It is part of IntoSQL Pro.
Create an API key
Sign in, open Settings, then API keys, and create a key. Keep it in an environment variable:
export INTOSQL_API_KEY="your-key"Every request sends it as a bearer token: Authorization: Bearer $INTOSQL_API_KEY.
Create a conversion from a URL
The quickest way is to give the API a public HTTPS address of the file. It downloads the file and converts it right away. The spec is the conversion request, the same one the command line and the browser use.
curl -X POST https://intosql.com/api/v1/conversions \
-H "Authorization: Bearer $INTOSQL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/exports/ventas.csv",
"spec": {"output": {"dialect": "postgresql"}}
}'The spec only has to name the database; every other field takes its default (Conversion spec). The answer is 202 Accepted, with the conversion queued and the whole spec filled in. name comes from the URL's file name, and bytes stays 0 until the file arrives.
{
"data": {
"id": "01J9Z8K3M4N5P6Q7R8S9T0V1W2",
"status": "queued",
"name": "ventas.csv",
"bytes": 0,
"spec": {
"version": 1,
"input": {
"format": null,
"encoding": null,
"delimiter": null,
"sheet": null,
"header_row": null
},
"output": {
"format": "sql",
"dialect": "postgresql",
"table": null,
"schema": null,
"create_table": true,
"column_names": "snake_case",
"style": "inserts",
"batch_rows": 500
},
"inference": {
"sample_rows": 10000,
"date_order": "auto",
"keep_leading_zeros": true,
"locale": null
},
"columns": []
},
"report": null,
"error": null,
"output": null,
"upload": null,
"created_at": "2026-10-16T14:02:11+00:00",
"started_at": null,
"finished_at": null,
"expires_at": "2026-10-17T14:02:11+00:00"
}
}To send a file from your computer instead, post name and bytes in place of url, PUT the file to the upload.url in the answer, then call POST /api/v1/conversions/{id}/start. See Conversions.
Wait for it to finish
Read the conversion until status is done or failed. It goes from queued to running to one of those two.
curl https://intosql.com/api/v1/conversions/01J9Z8K3M4N5P6Q7R8S9T0V1W2 \
-H "Authorization: Bearer $INTOSQL_API_KEY"When it is done, report holds the full report and output.url downloads the result:
{
"data": {
"id": "01J9Z8K3M4N5P6Q7R8S9T0V1W2",
"status": "done",
"name": "ventas.csv",
"bytes": 357,
"spec": {
"version": 1,
"input": {
"format": null,
"encoding": null,
"delimiter": null,
"sheet": null,
"header_row": null
},
"output": {
"format": "sql",
"dialect": "postgresql",
"table": null,
"schema": null,
"create_table": true,
"column_names": "snake_case",
"style": "inserts",
"batch_rows": 500
},
"inference": {
"sample_rows": 10000,
"date_order": "auto",
"keep_leading_zeros": true,
"locale": null
},
"columns": []
},
"report": {
"version": 1,
"input": {
"format": "csv",
"encoding": "windows-1252",
"delimiter": ";",
"sheet": null,
"bytes": 357
},
"dialect": "postgresql",
"table": "ventas",
"columns": [
{
"source_name": "Folio",
"name": "folio",
"sql_type": "text",
"kind": "text",
"precision": null,
"scale": null,
"max_chars": 5,
"nullable": false,
"fixes": [4],
"excluded": false,
"as_text": false
},
{
"source_name": "Fecha",
"name": "fecha",
"sql_type": "date",
"kind": "date",
"precision": null,
"scale": null,
"max_chars": null,
"nullable": false,
"fixes": [5],
"excluded": false,
"as_text": false
},
{
"source_name": "Importe",
"name": "importe",
"sql_type": "numeric(6,2)",
"kind": "decimal",
"precision": 6,
"scale": 2,
"max_chars": null,
"nullable": true,
"fixes": [6, 7],
"excluded": false,
"as_text": false
}
],
"rows": { "read": 5, "converted": 5, "rejected": 0 },
"fixes": [
{
"number": 1,
"code": "text_transcoded",
"column": null,
"row": null,
"args": { "encoding": "windows-1252" }
},
{
"number": 2,
"code": "header_found",
"column": null,
"row": 4,
"args": { "row": "4" }
},
{
"number": 5,
"code": "dates_day_first",
"column": "Fecha",
"row": null,
"args": {
"column": "Fecha",
"evidence": "15/02/2024",
"example": "03/02/2024",
"reading": "2024-02-03"
}
}
],
"problems": [],
"timings": { "read_ms": 2, "convert_ms": 1, "total_ms": 3 }
},
"error": null,
"output": {
"bytes": 686,
"url": "https://storage.example.com/01J9Z8K3M4N5P6Q7R8S9T0V1W2/ventas.sql?X-Amz-Expires=600&X-Amz-Signature=..."
},
"upload": null,
"created_at": "2026-10-16T14:02:11+00:00",
"started_at": "2026-10-16T14:02:12+00:00",
"finished_at": "2026-10-16T14:02:13+00:00",
"expires_at": "2026-10-17T14:02:11+00:00"
}
}The report above is shortened to three columns and three fixes; a real one lists every column and every fix. A failed conversion has status failed and the reason in error.
Download the result
output.url is a signed address that works for ten minutes. Read the conversion again for a fresh one.
curl -o ventas.sql "https://storage.example.com/01J9Z8K3M4N5P6Q7R8S9T0V1W2/ventas.sql?X-Amz-Expires=600&X-Amz-Signature=..."The file and the output are deleted 24 hours after the conversion was created, or right away with DELETE /api/v1/conversions/{id}.
The same with an SDK
The SDKs for TypeScript, PHP, Python, Java, Go, .NET and Ruby make the same calls. In TypeScript:
npm install @intosql/sdkconvertUrl creates the conversion and waits until it is done. spec() fills in the same defaults as the curl example.
import { IntoSQL, spec } from '@intosql/sdk';
const intosql = new IntoSQL({ apiKey: process.env.INTOSQL_API_KEY! });
const conversion = await intosql.convertUrl(
'https://example.com/exports/ventas.csv',
{
spec: spec({ dialect: 'postgresql' }),
},
);
console.log(conversion.report?.rows.converted, conversion.output?.url);For a file on disk, convert uploads it, starts the conversion and waits:
import { openAsBlob } from 'node:fs';
const conversion = await intosql.convert(await openAsBlob('ventas.xlsx'), {
name: 'ventas.xlsx',
spec: spec({ dialect: 'postgresql', table: 'ventas' }),
});A conversion that fails throws ConversionFailedError; a refused request throws IntoSQLError with a code such as needs_pro or over_quota. See the TypeScript SDK, or the SDK for your language.
Next steps
- The web converter: every option, the column editor and the report.
- How fixes work: what each fix means and how to turn it off.
- Command line:
convert,inspect,loadand the local MCP server. - API: authentication, limits and every endpoint.