Morningstar APImorningstar.no ↗
Search Nordic funds and ETFs on Morningstar Norway and retrieve portfolio exposure by world region, country, equity sector, and fixed-income sector.
What is the Morningstar API?
This API exposes two endpoints covering the Norwegian Morningstar market: search_funds for querying open-end funds and ETFs by name, ISIN, or ticker, and get_portfolio_exposure for retrieving portfolio weights across 10 world regions, a full country list, 11 equity sectors, and 6 fixed-income sector groups — each with fund, Morningstar category, and index breakdowns.
curl -X GET 'https://api.parse.bot/scraper/96d4b012-c12f-4647-87ae-4153de8d12a3/search_funds?query=DNB+Global' \ -H 'X-API-Key: $PARSE_API_KEY'
Typed, relational, agent-ready
A generated client with real types, enums, and the links between objects — the structure a flat JSON response can't carry. Autocompletes in your editor and reads cleanly to coding agents.
- Fully typed · autocompletes
- Objects link to objects
- Typed errors & pagination
Typed Python client. Set up the SDK in your uv project, then pull this API’s typed client:
uv add parse-sdk uv run parse init uv run parse add --marketplace morningstar-no-api
uv run parse add --marketplace pulls a pinned snapshot of this canonical API — it won’t change underneath you. To customize it, subscribe and swap to your own copy.
"""Walkthrough: Morningstar Nordics — search funds, then drill into portfolio exposure."""
from parse_apis.morningstar_no_api import Morningstar, FundNotFound
client = Morningstar()
# Search for funds by name; limit= caps total items fetched across all pages.
for fund in client.funds.search(query="DNB Global", limit=5):
print(fund.name, fund.isin, fund.base_currency)
# Drill into the first search hit's full portfolio exposure.
fund = client.funds.search(query="DNB Global", limit=1).first()
if fund is not None:
try:
exposure = fund.exposure()
except FundNotFound:
print("Fund was delisted or not found")
else:
print(exposure.fund_name, exposure.asset_type)
# Regional allocation vs category and index benchmarks
for row in exposure.regions.rows:
print(f" {row.name}: fund={row.fund_pct}% cat={row.category_pct}% idx={row.index_pct}%")
# Top country weights
for row in exposure.countries.rows[:5]:
print(f" {row.name}: {row.fund_pct}%")
# Equity sector breakdown
for row in exposure.equity_sectors.rows:
print(f" {row.name}: fund={row.fund_pct}% cat={row.category_pct}%")
print("exercised: funds.search / fund.exposure / regions / countries / equity_sectors")
Searches open-end funds and ETFs offered in the Nordic (Norway) market by name, ISIN or ticker, ranked by relevance. Each result row is one share class / exchange listing and carries security_id, the identifier accepted by get_portfolio_exposure. Paginated through page and limit: page defaults to 1, limit defaults to 20 and is clamped to 50; has_more tells whether a later page exists. total is the site's count of matching rows. One round trip. An empty results array is a valid response when nothing matches. Returns a validation error for a query containing characters other than letters, digits, spaces and . - & ' / ( ) + , : or longer than 80 characters.
| Param | Type | Description |
|---|---|---|
| page | integer | 1-based result page. |
| limit | integer | Rows per page; values above 50 are clamped to 50. |
| queryrequired | string | Fund name, ISIN or ticker fragment, e.g. a fund family and strategy name. |
{
"type": "object",
"fields": {
"page": "page returned",
"limit": "page size applied after clamping",
"query": "the search term as applied",
"total": "site-reported number of matching rows across all pages",
"results": "array of fund/ETF rows: security_id (consumed by get_portfolio_exposure), performance_id, name, isin, ticker (ETF listings only, else null), exchange (ETF listings only, else null), exchange_country (ISO3, ETF listings only), base_currency, investment_type ('fund' or 'etf')",
"has_more": "true when page < total_pages",
"total_pages": "site-reported number of pages at this limit"
},
"sample": {
"data": {
"page": 1,
"limit": 5,
"query": "DNB Global",
"total": 95,
"results": [
{
"isin": "NO0010337553",
"name": "DNB Global C",
"ticker": null,
"exchange": null,
"security_id": "F0GBR05LMO",
"base_currency": "NOK",
"performance_id": "0P000015GL",
"investment_type": "fund",
"exchange_country": null
},
{
"isin": "NO0012766031",
"name": "DNB Global L",
"ticker": null,
"exchange": null,
"security_id": "F00001EX9I",
"base_currency": "NOK",
"performance_id": "0P0001QBJR",
"investment_type": "fund",
"exchange_country": null
}
],
"has_more": true,
"total_pages": 19
},
"status": "success"
}
}About the Morningstar API
Search Nordic Funds and ETFs
search_funds accepts a query string (fund name fragment, ISIN, or ticker) and returns paginated rows of matching share classes and ETF listings available on Morningstar Norway. Each row carries a security_id, performance_id, name, isin, and — for exchange-listed products — a ticker. The total and total_pages fields let you walk through result sets; the limit parameter caps at 50 rows per page. The security_id from any result row is the key input for the second endpoint.
Portfolio Exposure Detail
get_portfolio_exposure takes a single security_id and returns four exposure breakdowns for that share class. The regions object contains rows for each of the 10 Morningstar world regions, each with fund_pct, category_pct, and index_pct, plus the three portfolio dates used (fund, category, index). The countries object provides fund_pct for every country in the Morningstar universe, including zero-weight entries. The equity_sectors object covers 11 Morningstar sectors, and fixed_income_sectors covers 6 groups — both with fund, category, and index percentages.
Response Context Fields
Every get_portfolio_exposure response includes fund_name, asset_type (e.g. EQUITY), category_name (the Morningstar peer group), index_name (the benchmark used for index comparisons), and the security_id echoed back. These make it straightforward to label and contextualize results without a separate lookup.
The Morningstar API is a managed, monitored endpoint for morningstar.no — not a raw scraper you maintain. Every endpoint is automatically health-checked on a schedule, and when morningstar.no changes and a check fails, the API is automatically queued for repair and re-verified. It is built to keep working as the site underneath it changes.
This isn't an official morningstar.no API — it's an independent, maintained REST wrapper over public data. Where the source has no official API (or only a limited one), Parse gives you a stable contract over a source that never promised one, and keeps it current. Need a new endpoint or field? You can revise it yourself in plain English and the agent rebuilds it against the live site in minutes — contributing the change back to the shared API is free.
Will this API break when the source site changes?+
Is this an official API from the source site?+
Can I fix or extend this API myself if I need a new endpoint or field?+
What happens if I call an endpoint that has an issue?+
- Screening Nordic funds by geographic tilt — e.g. identifying which funds in a Morningstar category are most overweight emerging markets relative to index_pct
- Comparing equity sector weights between a fund and its Morningstar category to surface active bets
- Building a fund-of-funds overlap tool using country-level fund_pct values from multiple security_ids
- Tracking fixed-income sector allocation shifts (government, corporate, securitized) across Nordic bond funds
- Populating a fund search widget with ISIN and ticker data for Norwegian retail investors
- Benchmarking a custom ETF portfolio against the Morningstar category average using category_pct fields
| Tier | Price | Credits/month | Rate limit |
|---|---|---|---|
| Free | $0/mo | 200 | 5 req/min |
| Hobby | $30/mo | 1,000 | 20 req/min |
| Developer | $100/mo | 5,000 | 100 req/min |
| Team | $300/mo | 20,000 | 300 req/min |
| Company | $1,000/mo | 100,000 | 500 req/min |
Each endpoint has a fixed posted price per successful call — most fall between 1 and 10 credits — shown on this API's page before you run it. Exceeding the rate limit returns a 429 response. Authenticate with the X-API-Key header.