Home / Guides / Streams, funds & search
Streams, funds & search

Analyze fund service providers with Form N-CEN

Parse Form N-CEN annual reports to see each fund series' custodians, administrators, pricing services, net assets and securities lending income.

Form N-CEN is the annual census report of registered investment companies. Each fund files it within 75 days of its fiscal year end, answering a fixed set of questions for every series: who the adviser, custodian, administrator, transfer agent and pricing services are, whether the fund lends securities and how much it earned doing so, its monthly average net assets, and which exemptive rules it relies on.

Because every fund answers the same questions in XML, N-CEN is the best public source for mapping the fund services industry.

Fetch recent N-CEN filings

GET /v1/n-cen returns N-CEN filings parsed to JSON. A single filing covers a whole registrant (a trust), with one entry per series under managementInvestmentQuestionSeriesInfo.

import os
from collections import Counter
import requests

BASE = "https://secfeedapi.com"
HEADERS = {"Authorization": f"Bearer {os.environ['SECFEED_KEY']}"}


def as_list(x):
    return x if isinstance(x, list) else [x] if x else []


def num(x):
    try:
        return float(x)
    except (TypeError, ValueError):  # N-CEN uses "N/A" for questions that do not apply
        return 0.0


r = requests.get(f"{BASE}/v1/n-cen", params={"startDate": "2026-09-01", "size": 100}, headers=HEADERS, timeout=120)
r.raise_for_status()
filings = r.json()["filings"]

series, custodians, admins, pricing, may_lend, lending_income = [], Counter(), Counter(), Counter(), 0, []
for f in filings:
    form = f["data"]["primary_doc"]["formData"]
    for q in as_list((form.get("managementInvestmentQuestionSeriesInfo") or {}).get("managementInvestmentQuestion")):
        series.append((form["registrantInfo"]["registrantFullName"], q["mgmtInvFundName"], num(q.get("mnthlyAvgNetAssets"))))
        for c in as_list((q.get("custodians") or {}).get("custodian")):
            custodians[c["custodianName"].upper()] += 1
        for a in as_list((q.get("admins") or {}).get("admin")):
            admins[a["adminName"].upper()] += 1
        for p in as_list((q.get("pricingServices") or {}).get("pricingService")):
            pricing[p["pricingServiceName"].upper()] += 1
        may_lend += q.get("isFundSecuritiesLending") == "Y"
        income = num(q.get("netIncomeSecuritiesLending"))
        if income > 0:
            lending_income.append((q["mgmtInvFundName"], income))

print(f"N-CEN filings since 2026-09-01: {len(filings)} | fund series: {len(series)}")
print(f"Series authorized to lend securities: {may_lend} | that earned lending income: {len(lending_income)}")
print("Top securities lending income:", "; ".join(f"{n[:32]} ${v:,.0f}" for n, v in sorted(lending_income, key=lambda x: -x[1])[:3]))
print("\nLargest series by monthly average net assets:")
for reg, fund, assets in sorted(series, key=lambda x: -x[2])[:5]:
    print(f"  {fund[:44]:<45}{reg[:30]:<31}${assets:,.0f}")
for title, counter in (("Custodians", custodians), ("Administrators", admins), ("Pricing services", pricing)):
    print(f"\n{title}:", ", ".join(f"{k.title()} ({v})" for k, v in counter.most_common(4)))

Output:

N-CEN filings since 2026-09-01: 54 | fund series: 431
Series authorized to lend securities: 311 | that earned lending income: 217
Top securities lending income: iShares Russell 2000 ETF $69,894,011; iShares Core S&P Small-Cap ETF $19,534,371; iShares Broad USD High Yield Cor $18,402,678

Largest series by monthly average net assets:
  iShares Core S&P 500 ETF                     iShares Trust                  $677,053,618,495
  iShares Russell 1000 Growth ETF              iShares Trust                  $114,693,625,157
  iShares Core S&P Mid-Cap ETF                 iShares Trust                  $99,105,197,891
  iShares Core S&P Small-Cap ETF               iShares Trust                  $84,743,550,568
  iShares Core S&P Total U.S. Stock Market ETF iShares Trust                  $75,014,493,749

Custodians: State Street Bank And Trust Company (144), Jpmorgan Chase Bank, N.A. (95), Citibank, N.A. (75), Euroclear Bank (60)

Administrators: State Street Bank And Trust Company (112), Jpmorgan Chase Bank, N.A. (78), Citi Fund Services Ohio, Inc. (73), The Bank Of New York Mellon (47)

Pricing services: Bloomberg L.P. (315), Ice Data Services, Inc. (193), S&P Global Inc. (166), London Stock Exchange Group Plc (156)

Notes on the data

  • One filing, many series. The 54 filings above contain 431 fund series. iShares Trust alone reports dozens, which is why its funds dominate the net assets list.
  • Lists or objects. XML elements that appear once come back as an object and repeated ones as a list. The as_list helper treats both the same way.
  • "N/A" answers. Questions that do not apply to a fund are answered "N/A", including numeric ones, so the num helper converts anything non-numeric to zero.
  • Authorized versus active lending. isFundSecuritiesLending says the fund may lend securities. netIncomeSecuritiesLending shows whether it actually earned anything in the year.

Other questions worth reading

Each series entry also includes:

  • investmentAdvisers and sub-advisers with their SEC file and CRD numbers
  • transferAgents, shareholderServicingAgents, brokerDealers and commissions paid
  • isExpenseLimitationInPlace and fee waiver answers
  • relyOnRuleTypes: exemptive rules such as Rule 32a-4
  • isSwingPricing, hasLineOfCredit and interfund lending details

ETFs and closed-end funds answer extra sections (for example authorized participants for ETFs), which appear as additional keys on the same filing.

Next steps

More streams, funds & search guides

Run this guide with your own key

500 free API calls a month. Every example on this page works on the free plan.

Get free API key →