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_listhelper 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
numhelper converts anything non-numeric to zero. - Authorized versus active lending.
isFundSecuritiesLendingsays the fund may lend securities.netIncomeSecuritiesLendingshows whether it actually earned anything in the year.
Other questions worth reading
Each series entry also includes:
investmentAdvisersand sub-advisers with their SEC file and CRD numberstransferAgents,shareholderServicingAgents,brokerDealersand commissions paidisExpenseLimitationInPlaceand fee waiver answersrelyOnRuleTypes: exemptive rules such as Rule 32a-4isSwingPricing,hasLineOfCreditand 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.