{% extends "base.html" %} {% from "_notes.html" import fine_print %} {% block title %}Import holdings from a CSV · Networthy HQ{% endblock %} {% block main_class %}wide{% endblock %} {% block content %}

Import holdings from a CSV

Any broker's export works — Zerodha Console, Groww, ICICI Direct, Trendlyne, Screener, or a sheet you keep yourself. We'll guess what each column is and show you the guess before anything is saved, so a format we've never seen still works.

{% if error %}
{{ error }}
{% endif %} {% if not sheet %}

Export as CSV — every broker offers it, and it reads far more reliably than a PDF. Nothing is saved until you've checked the columns on the next screen, and the file itself is never stored.

What it needs

Headers don't need to match anything. "Cur. val", "Market Value" and "Current Value (INR)" are all understood, and anything we get wrong you can correct on the next screen.

{% else %}

Check the columns

This is our guess at your file. Change anything that's wrong — the dropdowns list every column we found.

{% for key, label, _roots in fields %} {% endfor %}

{{ holdings|length }} holding{{ '' if holdings|length == 1 else 's' }}

₹{{ "{:,.0f}".format(total) }} total

Compare that total against what your broker shows. If it's wildly off, a column is mapped wrong — most often a cost column picked up instead of a market value.

{% for h in holdings[:12] %} {% endfor %}
HoldingISINCategoryQtyPriceValue
{{ h.name }} {{ h.isin or '—' }} {{ class_label(h.asset_class) }} {{ "{:,.3f}".format(h.units) if h.units else '—' }} {{ "{:,.2f}".format(h.price) if h.price else '—' }} ₹{{ "{:,.0f}".format(h.value) }}
{% if holdings|length > 12 %}

…and {{ holdings|length - 12 }} more.

{% endif %} {% if skipped %}

Skipped {{ skipped|length }} row{{ '' if skipped|length == 1 else 's' }} with no usable value: {{ skipped[:4]|join(', ') }}{{ '…' if skipped|length > 4 else '' }}.

{% endif %}
Start over

Importing again replaces everything from this file — it won't create duplicates. Holdings that also appear in an NSDL CAS or CAMS statement are matched on ISIN and counted once.

{% endif %} {{ fine_print("Values come from the file you upload. If your broker exports cost rather than market value, that's what will be imported — the total above is there to catch it.") }} {% endblock %}