Indian Mutual Fund NAV Scraper (AMFI)
Pricing
from $0.20 / 1,000 fund navs
Indian Mutual Fund NAV Scraper (AMFI)
Net asset values for Indian mutual fund schemes, from AMFI's own published file. One row per scheme: scheme code, name, fund house, category, the NAV and the trading date it belongs to. Wound-up schemes frozen at an old value are left out, not sold as current. History back to 2010.
Pricing
from $0.20 / 1,000 fund navs
Rating
0.0
(0)
Developer
Dami's Studio
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
20 hours ago
Last modified
Categories
Share
Net asset values for Indian mutual fund schemes, read from the file the Association of Mutual Funds in India publishes itself. One row per scheme: the AMFI scheme code, the scheme name, the fund house, the category it is filed under, the NAV, and the part that matters most: the trading date that NAV is actually for. No API key, no account, no browser.
- India only. AMFI publishes Indian schemes and nothing else, and this does not pretend to wider coverage.
- End-of-day published values, not a live price. A NAV is struck once per valuation day and published afterwards.
- Every row carries its own NAV date and how many days old that date was when the row was written.
- The published file is a cumulative register going back years, so a large share of it is schemes that were wound up long ago and are frozen at their final NAV. Those are left out by default instead of being sold to you as current.
- If the newest NAV anywhere in the file is older than your limit, the run charges nothing and says so. A stale file still answers with a perfectly normal HTTP 200, which is exactly why that check exists.
- A NAV that does not read as a number arrives as
nullwith the published text kept beside it. It is never turned into a zero. - Date-ranged history is available in the same row shape, back to 2010.
- Empty input returns a free sample row, so you can see the shape before spending anything.
Price
$0.20 per 1,000 NAV records, plus a $0.001 start fee per run.
This is a flat rate on every plan, free or paid. There are no volume tiers, no minimum spend, no subscription and no add-on fees. What you read here is what you pay on day one and on day four hundred.
| NAV records | Total cost |
|---|---|
| 100 | $0.021 |
| 1,000 | $0.201 |
| 10,000 | $2.001 |
| 50,000 | $10.001 |
One run returns at most 50,000 rows, so every line in that table is a single run and a single start fee.
For scale: the whole Indian market on a normal trading day is about 8,700 schemes with a current NAV. If you only want a handful of schemes, name them in schemeCodes and you pay for those and nothing else. Everything the filters drop is free.
What is actually charged
- One
fund-navevent per NAV record row written to the dataset. Nothing else is metered per row. - Free: the sample row an empty run returns, and every diagnostic row: a blocked target, a dead URL, a search that matched nothing. Those rows all carry
"charged": false. - Schemes dropped by any filter you set: scheme code, fund house, name or category.
- Schemes whose last published NAV is older than your
maxNavAgeDayslimit. - Every row in a run where the whole file failed a check: an unrecognised header, a stale file, a download that broke part-way, a format that changed shape.
- History rows whose date falls outside the range you asked for.
- A run that finds nothing costs the start fee and nothing more.
- Rows never leave the dataset without a charge, and are never charged without a row.
Input
{"mode": "latest","universe": "open","fundHouses": ["HDFC Mutual Fund"],"categoryContains": ["Large Cap"],"maxItems": 200,"maxNavAgeDays": 7}
| Field | What it does |
|---|---|
mode | latest for the daily published file, one row per scheme. history for a date range, one row per scheme per day. Default latest. |
universe | Which published file to read in latest mode: all, open, close or interval. all is every scheme AMFI lists and is the default. open is the one most people want: open-ended schemes you can still buy and sell. |
dateFrom / dateTo | history mode only. 2026-09-01 or 01-Sep-2026, either works. Leave them out and you get the last seven days. One run reads at most 366 days. |
maxItems | Total rows to return. Default 1,000, hard ceiling 50,000 per run. Rows come back in the file's own order (by category, then by fund house), so if you want particular schemes, filter rather than raising this. |
maxNavAgeDays | How old a scheme's last published NAV may be before it is skipped and not charged. Default 7 days, which covers a weekend and a public holiday. This is the setting that separates live schemes from wound-up ones. Raise it to 20000 and you get the entire historical register. |
maxFileAgeDays | The whole-file alarm. If the newest NAV anywhere in the published file is older than this, the run charges nothing at all and returns a row explaining what it found. Default 7 days. |
schemeCodes | AMFI scheme codes, exactly as published, for example ["119551","100047"]. The cheapest way to track a specific set of schemes every day. |
fundHouses | Match on the fund house name, case-insensitive, substring. ["HDFC"] catches HDFC Mutual Fund. |
nameContains | Match on the scheme name, case-insensitive, substring. Several terms act as "any of". |
categoryContains | Match on the category line, case-insensitive, substring. ["Large Cap"], ["Liquid"], ["ELSS"]. |
proxyUrls | Leave empty. It exists only for callers who want the traffic to leave through servers they already pay for, as http://user:pass@host:port. |
Run it with empty input and you get one clearly labelled sample row, free, so you can see the output shape before you spend anything.
Output
One row per NAV record. A real row from a real run:
{"ok": true,"charged": true,"recordType": "fund","schemeCode": "119551","schemeName": "Aditya Birla Sun Life Banking & PSU Debt Fund","fundHouse": "Aditya Birla Sun Life Mutual Fund","category": "Open Ended Schemes (Debt Scheme - Banking and PSU Fund)","categoryType": "Open Ended","plan": "Direct Plan","option": "IDCW-Re-investment","nav": 107.0677,"navRaw": "107.0677","currency": "INR","navDate": "2026-09-18","navDateRaw": "18-Sep-2026","navAgeDays": 2,"navStale": false,"isinGrowth": "INF209KA12Z1","isinReinvestment": "INF209KA13Z9","source": "daily-file","filePublishedAt": "2026-09-19T17:08:15.000Z","fileLatestNavDate": "2026-09-20","scrapedAt": "2026-09-20T10:41:02.118Z"}
Field notes
schemeCode: AMFI's own scheme code. It is the key to use: every code in the published file was unique when this was written, and it is stable across days, which the scheme name is not.schemeName: the name as that source writes it. The daily file and the history report do not write it the same way. The history report folds the plan and option into the name, so the same scheme reads asHDFC Multi-Cap Fundin one andHDFC Multi-Cap Fund-Direct Growthin the other. Match onschemeCode, not on the name.fundHouse: the asset management company, taken from the heading the schemes are grouped under.category: the category heading, normalised to one spacing. AMFI uses two spellings for several categories, so you will see bothEquity Scheme - Large Cap FundandEquity Schemes - Large Cap Fund, which are the same thing. Filter with a substring rather than an exact match.plan:Direct Plan,Regular Plan, or null. A lot of older close-ended schemes publish neither.option: growth, IDCW and their many spellings, as published. There are several hundred distinct strings across the file and they are not a controlled vocabulary, so treat this as text.nav: the net asset value as a number, in rupees. Null when the published value does not read as a number. Never zero, because a zero would be a price.navRaw: the value exactly as published, always, whether or not it parsed. This is here so you can see what was actually in the file rather than trusting the conversion.navDate: the trading date the NAV belongs to, asYYYY-MM-DD. Not the date you ran this. On a Monday morning the newest equity NAVs are still Friday's.navAgeDays: how many days oldnavDatewas when the row was written. The number to look at before you use a value.navStale: true whennavAgeDaysis past your limit. Under the default settings a charged row can never have this set, because stale rows are not charged.isinGrowth/isinReinvestment: the scheme's ISINs. Null where none is published, which is common on the growth-only variants and on the older close-ended schemes.filePublishedAt: when the published file itself was last written, as the server reports it. Useful as a second opinion on freshness, butnavDateis the one that decides whether a value is current.fileLatestNavDate: the newest NAV date found anywhere in the file that run read.latestmode only. If this is not close to today, nothing in the file is current.
Every real row carries "charged": true. Sample rows carry "_sample": true and diagnostic rows carry "_diagnostic": true with an errorCode you can filter on, and neither is ever billed.
How it works
- AMFI publishes the day's NAVs as a plain semicolon-separated text file and refreshes it in the evening, India time. The Actor reads that file straight over HTTP. There is nothing to log into and no page to render.
- The file is read as a stream and parsed line by line rather than loaded whole, so memory tracks the size of a chunk and not the size of the file. That is what lets a 366-day history pull run in the same small container as a single day.
- Columns are resolved from the file's own header line every run, by name. That is deliberate: the file has had columns added to it, and a parser that counts positions instead of reading labels would quietly start returning the word "Direct Plan" where the NAV should be. If the header is not one this Actor understands, the run stops and charges nothing rather than guessing.
- Before a single row is billed in
latestmode, the whole file is checked: that the header is known, that the rows have the number of columns the header declares, that dates parse, and that the newest NAV in the file is recent enough. Any of those failing means an uncharged row explaining which check failed. - In
historymode every row is checked against the dates you asked for, and rows outside that range are dropped and not charged. That is the check that would catch the report quietly ignoring its date parameters. - When you set a row limit, the download is cut off as soon as it is reached instead of pulling the rest and throwing it away.
What people use it for
- Keeping a portfolio tracker or a spreadsheet up to date without anyone retyping numbers off a website every evening.
- Filling in NAV history for a set of schemes after the fact: one run over a date range instead of one request per scheme per day.
- Reconciling a statement against the published value for the exact date on it, using the scheme code rather than trying to match names.
- Feeding a dashboard or an internal tool that needs the published figure and the date it belongs to, in the same row.
- Keeping your own archive. AMFI overwrites the daily file in place, so the only way to have last Tuesday is to have saved last Tuesday. Run this on a schedule and you are the archive.
The date on each row is the whole point: read this first
The published file is not a list of today's prices. It is a cumulative register of every scheme AMFI has listed, and each line carries the date of that scheme's last published NAV. A scheme that was wound up in 2016 is still in the file, still answering with a plausible-looking number, still at HTTP 200.
Measured on 20 September 2026, on the file covering every scheme:
| NAV date on the row | Rows |
|---|---|
| 18 September 2026, the previous trading day | 7,982 |
| 20 September 2026, that morning | 706 |
| Anything earlier, back to April 2016 | 5,687 |
| Total rows in the file | 14,375 |
So on that day only about 60% of the file was current. The rest were schemes that have stopped trading, frozen at whatever their last value was. Nothing in the response marks them as dead. The only thing distinguishing a live scheme from one that closed nine years ago is the date in the last column.
That is why maxNavAgeDays defaults to 7 and why rows past it are not charged. You get the current market by default. If you want the full register (and there are good reasons to, such as looking up what a scheme was worth before it closed), set maxNavAgeDays high and every row arrives with navStale and its real age on it.
The 706 rows dated that same morning are not an anomaly. Liquid and overnight schemes strike a NAV every calendar day, weekends included, so they run a day ahead of the equity schemes. Both are correct.
End of day, not live
A mutual fund NAV is not a quoted price that moves during the session. It is calculated once per valuation day from the scheme's holdings at the close, and published afterwards, in the evening, India time. There is no intraday value to scrape, from here or anywhere else.
What follows from that: run this once a day, after the file has been refreshed, and you have everything there is. Running it hourly gets you the same numbers and costs you more. Check filePublishedAt and fileLatestNavDate on your first run of the day if you want to know whether the evening refresh has landed yet.
This Actor returns published NAV records and the dates they belong to. It does not rank schemes, calculate returns, or suggest anything about what to do with them.
The two sources, and what differs between them
latest mode reads the daily published file. One row per scheme, carrying that scheme's most recent published NAV. Four universes are available: all (every scheme, about 14,400 rows), open (open-ended schemes, about 9,600), close (close-ended, about 4,700) and interval (about 40). Most people want open.
history mode reads AMFI's date-ranged report. One row per scheme per day, back to 2010. Roughly 8,500 schemes publish on a typical trading day, so a week is around 42,000 rows and a month around 160,000. Use maxItems and the filters, or the bill grows quickly. One run covers at most 366 days.
Two differences worth knowing before you join them:
- The two sources order their columns differently and name the scheme differently. The history report folds the plan and option into the scheme name; the daily file keeps them in their own columns. Join on
schemeCode, which is the same in both. - The history report is generated when you ask for it, so the first bytes can take 20 to 30 seconds on a long range. The daily file answers immediately.
No NAV is published on weekends or Indian public holidays, apart from the liquid and overnight schemes. A history range covering only a weekend legitimately returns nothing, and that costs you nothing.
Reading the output
Every run writes three kinds of row and they are easy to tell apart.
- Real rows carry
"charged": trueand"recordType": "fund". One billed event each. - The sample row carries
"_sample": trueand"charged": false. There is exactly one, it only appears when you ran with no input at all, and it is there so you can see the shape before spending anything. - Diagnostic rows carry
"_diagnostic": true,"charged": falseand anerrorCodeyou can switch on:
errorCode | What happened |
|---|---|
FILE_STALE | The file was served normally but the newest NAV in it is past your age limit. Nothing was charged. |
FORMAT_UNRECOGNISED | The header line is not one this Actor knows. Nothing was parsed and nothing was charged. |
FORMAT_DRIFT | Too many rows did not match the column count the header declares. Nothing was charged. |
FEED_TRUNCATED | The download stopped part-way. In latest mode nothing is charged, because a half-read file cannot be checked. |
FEED_HTTP | The source answered with an error status. |
FEED_EMPTY | The file contained no readable scheme rows. |
NO_DATE | Not one row carried a readable date. |
ALL_STALE | Your filters matched schemes, but every one of them last published a NAV past your age limit. |
RANGE_MISMATCH | In history mode, rows came back dated outside the range you asked for. They were dropped. |
NO_RESULTS | Nothing matched your filters. |
INPUT_ADJUSTED | Something in the input was out of bounds and was clamped. The row says what changed. |
If you only want data, filter on charged == true. The count of those rows is exactly the number of events you were billed for, so the dataset is its own invoice.
Limitations
- India only. AMFI publishes Indian mutual fund schemes. There is no equivalent open daily file for the United States, the United Kingdom or anywhere else, and this does not cover them.
- End-of-day values only. There is no intraday NAV to return, because one is not calculated.
- The NAV is the only figure here. No assets under management, no expense ratio, no holdings, no returns, no ratings. None of that is in the published file.
- On a typical day roughly four rows in ten of the full file belong to schemes that have stopped trading. Under the default age limit you will not be charged for them and will not see them; if you raise the limit you get them, flagged.
- The
optionfield is free text with several hundred distinct spellings across the file. It is not a controlled vocabulary and should not be used as a join key. - The scheme name differs between the daily file and the history report for the same scheme, because one folds the plan and option into it. Join on
schemeCode. - Categories appear under two spellings for several types,
Equity Scheme -andEquity Schemes -. Filter on a substring. - Dates are published without a time zone and are read as calendar dates in UTC. That is fine for day-level work and would matter if you were comparing timestamps to the hour.
- The history report is generated on request, so a long range can take 20 to 30 seconds before the first row arrives, and a very long one can approach the run time limit.
- One run returns at most 50,000 rows and covers at most 366 days of history. Longer histories need more than one run.
- No NAV is published on weekends or Indian public holidays for most schemes, so a short history range can legitimately come back empty.
- Rows arrive in the file's own order, grouped by category and then by fund house. If you cut a run short with a low
maxItemsyou get the first categories alphabetically, not a spread across the market. Use the filters instead.
Questions
Which market does this cover?
India, and only India. The data comes from the file the Association of Mutual Funds in India publishes for the Indian market. Every scheme in it is an Indian scheme and every value is in rupees.
Is the NAV live?
No, and it cannot be. A mutual fund NAV is struck once per valuation day from the closing holdings and published in the evening, India time. Every row tells you which trading day its value belongs to, in navDate, and how old that was when the row was written, in navAgeDays.
Why would a row be dated years ago?
Because the scheme stopped trading and the published file keeps it, frozen at its final value. The file is a register of everything AMFI has listed, not a list of what is live. Those rows are skipped and not charged unless you raise maxNavAgeDays on purpose.
What happens if the published file stops being updated?
The run reads it, notices that the newest NAV in the whole file is past your maxFileAgeDays limit, writes one free row saying so with the date it found, and charges nothing. That check exists because a file that has stopped moving still answers with a normal HTTP 200 and looks completely healthy.
Can I get history?
Yes. Set mode to history with dateFrom and dateTo and you get one row per scheme per day in the same shape, back to 2010. Use the filters and maxItems, because a month of the whole market is around 160,000 rows.
How do I track just a few schemes?
Put their AMFI codes in schemeCodes. You are charged only for the rows that come back, and everything the filter drops is free. It is the cheapest way to run this daily.
How do I find a scheme code?
Run it once with nameContains set to part of the scheme name and read schemeCode off the rows. Then use the code from then on: names change wording, codes do not.
Do I need an API key or a proxy?
Neither. The file is published openly and the run brings its own egress. The proxyUrls field is only there for callers who want traffic to leave through servers they already own.
Will the run fail if something goes wrong?
No. A stale file, a changed format, a broken download or a filter that matched nothing all produce an uncharged row explaining what happened, and the run still finishes as succeeded. A failed run would still bill the start fee, which would mean paying to be told something went wrong.
Does it tell me which funds to buy?
No. It returns the values that were published and the dates they belong to. It does not rank anything, calculate returns, or make recommendations.
Can I run it on a schedule?
Yes, and once a day in the evening India time is the right cadence, because that is when the file is refreshed, and running it more often returns the same numbers. Key on schemeCode plus navDate to match rows across runs.