<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kizuki</title>
    <description>The latest articles on DEV Community by Kizuki (@kizukidata).</description>
    <link>https://dev.to/kizukidata</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4242158%2Fba27025e-d476-427a-8c3a-d2af1d5c2a96.png</url>
      <title>DEV Community: Kizuki</title>
      <link>https://dev.to/kizukidata</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kizukidata"/>
    <language>en</language>
    <item>
      <title>Canada's approved LMIA positions fell 28% in 2025. Employers on both years' lists lost 8%; first-time employers fell by half.</title>
      <dc:creator>Kizuki</dc:creator>
      <pubDate>Fri, 13 Nov 2026 11:29:53 +0000</pubDate>
      <link>https://dev.to/kizukidata/canadas-approved-lmia-positions-fell-28-in-2025-employers-on-both-years-lists-lost-8-11fc</link>
      <guid>https://dev.to/kizukidata/canadas-approved-lmia-positions-fell-28-in-2025-employers-on-both-years-lists-lost-8-11fc</guid>
      <description>&lt;p&gt;Every quarter, Employment and Social Development Canada (ESDC) publishes the list of employers that received a positive Labour Market Impact Assessment (LMIA), the approval most employers need before hiring a temporary foreign worker. The news coverage we found reads each list on its own: who got the most positions, how the total moved.&lt;/p&gt;

&lt;p&gt;We linked the lists together instead. With 36 quarters, 2017Q3 to 2026Q2, you can ask whether the employers on this year's list were on last year's.&lt;/p&gt;

&lt;p&gt;Linking the lists across years shows two things that single-quarter totals miss:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Outside agriculture, the employers on the list change a lot from year to year. In 2022, 2023 and 2024, about half of all employers on the list had no positive LMIA in the previous three years. Most of those newcomers are small: employers seen in the previous three years still held 71% to 75% of the approved positions.&lt;/li&gt;
&lt;li&gt;Approved positions on the list fell 28.1% from 2024 to 2025, but employers that were on both lists lost 7.9%. Most of the drop sits with employers that had no approval in 2025. The biggest missing group is first-time employers, and past employers also came back less often.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Data
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;36 quarterly files, 404,620 rows. Each row is an employer, location, stream and occupation with a count of approved positions. The 2016 and January to June 2017 lists are used only to check who had appeared before.&lt;/li&gt;
&lt;li&gt;We checked our parsing of the 2026Q2 file against ESDC's published spreadsheet: 7,344 rows and 21,515 positions in both.&lt;/li&gt;
&lt;li&gt;Streams: High Wage, Low Wage, Primary Agriculture, Global Talent Stream, and Permanent Resident Only. ESDC excluded the Permanent Resident Only LMIAs from 2018Q1 to 2023Q3, so we ran the headline numbers with and without that stream. Each table says which.&lt;/li&gt;
&lt;li&gt;All figures cover employers named on the list; ESDC withholds some names (see Finding 3).&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The hard part: deciding when two rows are the same employer
&lt;/h2&gt;

&lt;p&gt;The earlier work we found did not follow employers from one year to the next. O'Donnell and Skuterud (2022) used the same lists for 2016 to 2019 and counted employers within each year. They noted that "a complication in merging the data across quarters at the employer level are inconsistencies in the recording of employer names" (CLEF Working Paper 39, footnote 18).&lt;/p&gt;

&lt;p&gt;ESDC says employer names are typed in by hand and "subject to potential data entry error and inconsistent spelling". If spelling drift split one employer into two, it would look like one employer leaving and another arriving. So we matched employers three ways:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Rule&lt;/th&gt;
&lt;th&gt;Distinct employers, 2017Q3–2026Q2&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;A&lt;/td&gt;
&lt;td&gt;Normalised name: accents, case, punctuation and legal-form words (Inc, Ltd, Ltée, Corp, S.E.C.) removed&lt;/td&gt;
&lt;td&gt;131,678&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;B&lt;/td&gt;
&lt;td&gt;A plus the first three characters of the postal code&lt;/td&gt;
&lt;td&gt;139,003&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;C&lt;/td&gt;
&lt;td&gt;A, then names merged when their string-similarity ratio is at least 0.95, 0.90 or 0.85&lt;/td&gt;
&lt;td&gt;128,499 to 130,785&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;B splits too much (one company with two sites becomes two employers). C at 0.85 merges too much (we sampled the merges and found unrelated companies chained together). The year-to-year shares, the decomposition of the decline and the first-timer split below were run under A, B, C at 0.85 and C at 0.95. The numbers move by a few points between methods, and none of the conclusions below change. We quote method A.&lt;/p&gt;

&lt;p&gt;As a check within each quarter, ESDC publishes its own count of unique employers with a positive LMIA, summed over provinces. For the High Wage stream, where almost no names are withheld, our count summed the same way is 97.6% to 98.9% of ESDC's in every quarter from 2025Q1 to 2026Q2. That checks the parsing and the matching within a quarter. It says little about spelling drift between quarters, which the checks further down address.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 1: in 2022 to 2024, about half of the employers had no approval in the previous three years
&lt;/h2&gt;

&lt;p&gt;Share of each year's employers that were also on the previous year's list (method A, all streams including Permanent Resident Only):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;Employers&lt;/th&gt;
&lt;th&gt;Also on last year's list&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;21,037&lt;/td&gt;
&lt;td&gt;31.5%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2020&lt;/td&gt;
&lt;td&gt;19,609&lt;/td&gt;
&lt;td&gt;40.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2021&lt;/td&gt;
&lt;td&gt;19,426&lt;/td&gt;
&lt;td&gt;42.2%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2022&lt;/td&gt;
&lt;td&gt;34,947&lt;/td&gt;
&lt;td&gt;31.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;46,843&lt;/td&gt;
&lt;td&gt;36.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;55,599&lt;/td&gt;
&lt;td&gt;37.0%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025&lt;/td&gt;
&lt;td&gt;37,200&lt;/td&gt;
&lt;td&gt;46.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;A one-year look overstates churn, because an employer only needs an LMIA when it hires. Some skip a year and come back. Take the employers that were on the list in a year from 2018 to 2022 and missing the next year. Between 29% and 51% of them were back two or three years later. Between 41% and 57% had still not returned by mid-2026. Leaving out Permanent Resident Only changes these shares by less than one point.&lt;/p&gt;

&lt;p&gt;So we widened the memory to three years. The share of employers seen anywhere in the previous three years was 49.5% in 2022, 45.6% in 2023 and 48.8% in 2024. In those years, roughly half of the employers on the list were new or back after three years or more. Earlier years were less complete on the public list (see the checks below). An employer left off one year's list and listed later counts as new, so these shares may understate how many had been seen before; 2022 is the most exposed, because its look-back years were the least complete. In 2025 the share seen in the previous three years rose to 65.6%, as newcomers fell away (Finding 2). Part of that rise may come from better coverage of the look-back years; the one-year share, whose previous year was covered about equally (90.7% and 91.1%), also rose, from 37.0% to 46.7%.&lt;/p&gt;

&lt;p&gt;By positions the picture is different. Employers that had an approval in the previous three years held 75.1% of approved positions in 2022, 70.7% in 2023 and 71.6% in 2024. The turnover is mostly among employers approved for one or two positions.&lt;/p&gt;

&lt;p&gt;Agriculture is the exception. In Primary Agriculture, 63.6% to 77.4% of employers were on the previous year's list in every year from 2019 to 2025. High Wage has the least repeat use: 74% to 82% of each year's High Wage employers held no High Wage approval the year before. Part of that is employers moving between streams, which we come back to below.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 2: the 2025 drop is mostly missing newcomers
&lt;/h2&gt;

&lt;p&gt;From September 26, 2024, ESDC stopped processing Low Wage LMIAs in census metropolitan areas with unemployment of 6% or more (with exceptions for food security sectors, construction and health care), cut the Low Wage cap to 10% of an employer's workforce, and cut Low Wage employment from two years to one. From October 28, 2024, employers had to send verifiable documents proving their business was legitimate, instead of an attestation from a lawyer or accountant. Under ESDC's current guidance, an employer other than a private household whose most recent LMIA decision was positive and issued in the past two years can skip the documents showing that the business provides a good or service and can meet the terms of the job offer. First-time employers do not qualify. From November 8, 2024, the High Wage threshold rose to the provincial median wage plus 20%.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp6jvqbzyo3wprdszu2te.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fp6jvqbzyo3wprdszu2te.png" alt="Approved LMIA positions by employer group, 2019-2025, excluding Permanent Resident Only" width="800" height="569"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Approved positions across all streams, including Permanent Resident Only, fell by 64,227 from 2024 to 2025. Split by employer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Employers on both lists: −10,773 (17% of the drop).&lt;/li&gt;
&lt;li&gt;Employers on only one of the two lists: −53,454 (83%).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The employers on both lists lost 7.9% of their positions, close to their change a year earlier (−6.1% from 2023 to 2024, when the total grew 0.5%).&lt;/p&gt;

&lt;p&gt;That split alone proves little, since a large part of the list changes every year anyway. From here on we leave out Permanent Resident Only, which brings the fall to 62,341. Here a new arrival is an employer with no approval in the previous calendar year. We asked how far 2025 fell short of what 2024's turnover would have produced. We compared 2025 with 2024's rates: the share of positions that new arrivals brought in, the share that employers dropping off the list took out, and the rate at which staying employers shrank. Measured against those three rates one at a time, 2025 came in 63,527 positions short. Of that shortfall:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;70.1% is fewer positions from new arrivals,&lt;/li&gt;
&lt;li&gt;27.7% is more employers with no approval in 2025,&lt;/li&gt;
&lt;li&gt;2.3% is staying employers shrinking faster.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Across the four matching methods and three baselines (2024, 2023–2024, 2019 with 2023–2024), the new-arrival share ranges from 53.6% to 71.8%. For the first half of 2026 against the first half of 2025, with baseline rates from the first halves of 2024 and 2023, it is 73.5% to 79.2%. None of these baselines is a clean "before". 2024 already includes the last quarter after the September and November rules, and 2022 to 2024 were boom years for the program. Part of the shortfall may be a return to a lower normal.&lt;/p&gt;

&lt;p&gt;We split new arrivals into first-timers (on no list since 2016) and returners (on an earlier list, then away for at least a year). The last column is returners as a share of all past employers that were not on the previous year's list:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Year&lt;/th&gt;
&lt;th&gt;First-timers&lt;/th&gt;
&lt;th&gt;Their positions&lt;/th&gt;
&lt;th&gt;Returners&lt;/th&gt;
&lt;th&gt;Their positions&lt;/th&gt;
&lt;th&gt;Share of past employers that returned&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2019&lt;/td&gt;
&lt;td&gt;11,442&lt;/td&gt;
&lt;td&gt;28,859&lt;/td&gt;
&lt;td&gt;2,965&lt;/td&gt;
&lt;td&gt;9,892&lt;/td&gt;
&lt;td&gt;19.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2023&lt;/td&gt;
&lt;td&gt;23,169&lt;/td&gt;
&lt;td&gt;59,100&lt;/td&gt;
&lt;td&gt;5,796&lt;/td&gt;
&lt;td&gt;19,774&lt;/td&gt;
&lt;td&gt;14.9%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2024&lt;/td&gt;
&lt;td&gt;26,133&lt;/td&gt;
&lt;td&gt;58,802&lt;/td&gt;
&lt;td&gt;8,327&lt;/td&gt;
&lt;td&gt;25,330&lt;/td&gt;
&lt;td&gt;16.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025&lt;/td&gt;
&lt;td&gt;12,044&lt;/td&gt;
&lt;td&gt;20,897&lt;/td&gt;
&lt;td&gt;7,944&lt;/td&gt;
&lt;td&gt;18,752&lt;/td&gt;
&lt;td&gt;11.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;First-timers fell 53.9% from 2024 to 2025, and their positions fell by 37,905, the largest single piece of a net decline of 62,341. The 2025 count is close to 2019's, so part of this is a fall back from the boom (2019 has a shorter history, which inflates its first-timer count). Returners fell 4.6% in number but 26.0% in positions. The pool of past employers that could return grew from 51,002 to 68,658, so the share that came back fell from 16.3% to 11.6%. Both groups shrank, and first-timers shrank much faster. Comparing matching first halves, first-timers were 43.7% of employers in the first half of 2024, 31.2% in the first half of 2025 and 21.2% in the first half of 2026.&lt;/p&gt;

&lt;p&gt;Most of the first-timer drop was in Low Wage. Counting each employer in the stream where it had the most positions, Low Wage accounts for 77% to 80% of the drop in first-timers and 62% to 65% of the drop in their positions; the range comes from how employers with the same number of positions in two streams are assigned. High Wage first-timers also fell, by 26% to 29%. In Low Wage, 82.7% of 2024's employers got no Low Wage LMIA in 2025.&lt;/p&gt;

&lt;p&gt;The October 2024 document rule applies to every first-time employer, so it is the first explanation to test. It does not account for the whole drop. Employers coming back after three or more years without an approval do not meet the two-year condition either, as far as the list shows. There were 2,908 of them in 2024 and 2,927 in 2025, so their number did not fall, although their share of the pool of such employers fell from 8.8% to 6.9%. Employers last approved two years earlier, many of whom would be exempt, came back less often as well: their return rate fell from 30.3% to 19.3%. The list shows approvals only, and the two-year window does not line up with calendar years, so this is a rough test.&lt;/p&gt;

&lt;p&gt;Because the list records approvals only, it cannot separate employers that stopped applying, applications ESDC refused to process under the 6% unemployment rule, and applications assessed and refused (ESDC publishes those employers in a separate Negative LMIA list). The labour market also cooled over the same period. These figures describe what changed, not why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Finding 3: from late 2025 a much larger share of Low Wage employers is missing from the public list
&lt;/h2&gt;

&lt;p&gt;ESDC's list leaves out "all personal names, such as employers of caregivers or business names that use or include personal names". Comparing the list with ESDC's own unique-employer counts shows how much that leaves out. ESDC gives Low Wage counts only by province, so for the last column we counted the list by province too, which counts an employer with sites in two provinces twice on both sides. The other columns include Permanent Resident Only, to match ESDC's all-stream total.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Quarter&lt;/th&gt;
&lt;th&gt;ESDC unique employers&lt;/th&gt;
&lt;th&gt;On the public list&lt;/th&gt;
&lt;th&gt;Missing&lt;/th&gt;
&lt;th&gt;Low Wage employers on the list&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;2025Q1&lt;/td&gt;
&lt;td&gt;16,307&lt;/td&gt;
&lt;td&gt;14,905&lt;/td&gt;
&lt;td&gt;8.6%&lt;/td&gt;
&lt;td&gt;81.4%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025Q2&lt;/td&gt;
&lt;td&gt;14,390&lt;/td&gt;
&lt;td&gt;13,113&lt;/td&gt;
&lt;td&gt;8.9%&lt;/td&gt;
&lt;td&gt;82.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025Q3&lt;/td&gt;
&lt;td&gt;11,298&lt;/td&gt;
&lt;td&gt;10,060&lt;/td&gt;
&lt;td&gt;11.0%&lt;/td&gt;
&lt;td&gt;78.3%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2025Q4&lt;/td&gt;
&lt;td&gt;10,409&lt;/td&gt;
&lt;td&gt;8,747&lt;/td&gt;
&lt;td&gt;16.0%&lt;/td&gt;
&lt;td&gt;64.7%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026Q1&lt;/td&gt;
&lt;td&gt;9,731&lt;/td&gt;
&lt;td&gt;7,880&lt;/td&gt;
&lt;td&gt;19.0%&lt;/td&gt;
&lt;td&gt;53.6%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2026Q2&lt;/td&gt;
&lt;td&gt;7,701&lt;/td&gt;
&lt;td&gt;6,501&lt;/td&gt;
&lt;td&gt;15.6%&lt;/td&gt;
&lt;td&gt;61.8%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The number of missing Low Wage employers stayed between about 1,100 and 1,600 a quarter. The share rose because the listed Low Wage employers fell.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ihhhr7y8xe18q8m73iy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F5ihhhr7y8xe18q8m73iy.png" alt="Share of ESDC's unique employers on the public list, High Wage and Low Wage" width="800" height="427"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;High Wage stayed between 97.6% and 98.9% in every quarter. Over the first five quarters, the share of ESDC's employers in NAICS 81 (Other services, which includes private households) rose from 11.0% to 20.1%, then eased to 17.6% in 2026Q2. That fits the idea that the missing employers are mostly households hiring caregivers. It also fits households holding steady while other Low Wage employers fell away. ESDC does not break unique employers down by occupation or by 3-digit industry, so we cannot tell these apart.&lt;/p&gt;

&lt;p&gt;If the withheld employers include first-time employers, some of the first-timer drop after mid-2025 is employers the public list no longer shows. We did not adjust the 2024 to 2025 comparison for this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checks that could have broken the result
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Spelling drift between years: for each year, we counted leavers that had a similar-named new arrival in the same postal area. That is 6.8% to 12.5% of leavers. Counting all of them as the same employer raises the 2024 "also last year" share from 37.0% to about 43% under this check. Spelling changes that come with a new address are not caught.&lt;/li&gt;
&lt;li&gt;Seasonality: comparisons are calendar year to calendar year, or first half to first half.&lt;/li&gt;
&lt;li&gt;Short history: adding the 2016 and early 2017 lists as history lowers the yearly first-timer counts by 1.0% to 2.4% for 2022 to 2025, and by more in earlier years (37.4% in 2018, 13.2% in 2019, 3.4% in 2021). The first-timer counts in this post include that history. Counting Permanent Resident Only approvals as earlier history too changes the 2024 and 2025 first-timer counts to 25,993 and 11,814, a fall of 54.5% instead of 53.9%.&lt;/li&gt;
&lt;li&gt;Coverage of earlier years: ESDC's annual counts of unique employers with a positive LMIA (&lt;a href="https://open.canada.ca/data/en/dataset/76defa14-473e-41e2-abfa-60021c4d934b" rel="noopener noreferrer"&gt;Table 19 of its 2018 to 2025 statistics&lt;/a&gt;) show that the public list had 58.5% as many employers as ESDC counted in 2018, 70.6% to 75.0% as many in 2019 to 2021, 80.7% in 2022 and 87.6% to 91.1% in 2023 to 2025. Leaving out the Permanent Resident Only stream gives the same pattern. An employer left off an earlier year's list that appears later counts as new here, so comparisons with earlier years, including the three-year look-back for 2022, may overstate how many employers were new. Employers that are left off every year do not have this effect, and the counts cannot tell how many of the missing employers are of each kind.&lt;/li&gt;
&lt;li&gt;2021Q3 has about 60% of the rows of nearby quarters; dropping 2021 does not change the 2025 results.&lt;/li&gt;
&lt;li&gt;Stream switching: the threshold change was expected to move 34,000 positions from High Wage to Low Wage, whereas the lists show movement mainly from Low Wage into High Wage. In 2025, 2,812 of the 13,459 employers new to High Wage (20.9%) had a Low Wage approval in 2024, against 4% to 10% in earlier years. That equals 10.5% of the employers that left Low Wage. Within the same employer and occupation the move is smaller: 872 of 19,307 pairs (4.5%). Either way it explains only a minority of the Low Wage exits. The expected High-to-Low move may not show up because many of those positions were not approved under the Low Wage rules. Occupation codes changed from NOC 2011 to NOC 2021 in late 2022, so the occupation-level comparison with earlier years is rough.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Two limits pull in opposite directions. Under the Recognized Employer Pilot, repeat employers could get LMIAs valid for up to 36 months and keep hiring without appearing on next year's list, so some apparent leavers may still employ workers. From May 1, 2024, new LMIAs were valid for six months instead of 18, which makes employers apply again sooner and pushes the 2025 "also last year" share of 46.7% up.&lt;/p&gt;

&lt;h2&gt;
  
  
  The data behind this post
&lt;/h2&gt;

&lt;p&gt;The quarterly and annual flow tables (new, returning, first-time and lapsed employers and their positions, by stream and province, no employer names) are in the &lt;a href="https://huggingface.co/datasets/kizukidata/canada-lmia-employer-flows" rel="noopener noreferrer"&gt;dataset on Hugging Face&lt;/a&gt;. The yearly and quarterly employer and position counts in this post can be checked against these tables. The counts in the dataset use history from 2017Q3 only, so its first-time counts for 2022 to 2025 are 1% to 2% higher than the ones above.&lt;/p&gt;




&lt;p&gt;We publish Actors on the Apify Store as Kizuki, so we are not a neutral party.&lt;/p&gt;

&lt;p&gt;Contains information licensed under the &lt;a href="https://open.canada.ca/en/open-government-licence-canada" rel="noopener noreferrer"&gt;Open Government Licence – Canada&lt;/a&gt;. Source: Employment and Social Development Canada, Positive LMIA Employers List and TFWP LMIA Quarterly Statistics. Not affiliated with or endorsed by ESDC or the Government of Canada.&lt;/p&gt;

&lt;p&gt;Disclosure: This article was created with the help of AI; we checked the figures against the published lists and ESDC's statistics, and the policy dates against ESDC's own pages.&lt;/p&gt;

</description>
      <category>opendata</category>
      <category>canada</category>
      <category>immigration</category>
      <category>datascience</category>
    </item>
    <item>
      <title>What 107,156 Apify Store Actors Reveal About User Concentration, and How to Keep Counting After Nov 15</title>
      <dc:creator>Kizuki</dc:creator>
      <pubDate>Fri, 13 Nov 2026 04:46:31 +0000</pubDate>
      <link>https://dev.to/kizukidata/what-107156-apify-store-actors-reveal-about-user-concentration-and-how-to-keep-counting-after-nov-11p2</link>
      <guid>https://dev.to/kizukidata/what-107156-apify-store-actors-reveal-about-user-concentration-and-how-to-keep-counting-after-nov-11p2</guid>
      <description>&lt;p&gt;Between November 3 and 4, 2026 (UTC), we pulled 107,156 Actors across 8,714 authors from the public Apify Store API. Just 101 authors (1.2%) accounted for 80.1% of summed 30-day Actor users, while 56.3% of Actors had 1 user and 18.1% had 0. Nine days later, the catalog had grown to 119,113 listings. On November 15, 2026, &lt;code&gt;GET /v2/store&lt;/code&gt; moves to a new search backend that breaks standard pagination and drops several stats fields.&lt;/p&gt;

&lt;p&gt;This post reports the full-catalog numbers and a matched cohort of recent launches, then a Python script that keeps working after November 15.&lt;/p&gt;

&lt;h2&gt;
  
  
  User concentration across 107,156 Actors
&lt;/h2&gt;

&lt;p&gt;Apify's Store catalog expanded rapidly in 2026. In our November 4 snapshot (&lt;code&gt;107,156&lt;/code&gt; Actors fetched out of &lt;code&gt;108,603&lt;/code&gt; reported by the API), an estimated &lt;code&gt;90.5%&lt;/code&gt; (&lt;code&gt;96,953&lt;/code&gt;) of existing Actors were created in 2026, including &lt;code&gt;29,161&lt;/code&gt; in October alone. An estimated &lt;code&gt;81%&lt;/code&gt; of authors (&lt;code&gt;7,021&lt;/code&gt; of &lt;code&gt;8,714&lt;/code&gt;) published their first Actor in 2026; this estimate probably overcounts new authors, because we took each author's oldest listed Actor as their first.&lt;/p&gt;

&lt;p&gt;By November 13, 2026 (&lt;code&gt;02:08 UTC&lt;/code&gt;), a fresh public API check showed &lt;code&gt;119,113&lt;/code&gt; total catalog entries, an increase of &lt;code&gt;10,510&lt;/code&gt; listings in 9 days, or roughly &lt;code&gt;1,168&lt;/code&gt; new entries per day.&lt;/p&gt;

&lt;p&gt;Usage has not spread evenly across that supply. In the November 4 snapshot:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;30-day users (&lt;code&gt;totalUsers30Days&lt;/code&gt;)&lt;/th&gt;
&lt;th&gt;Actors&lt;/th&gt;
&lt;th&gt;Share&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;19,352&lt;/td&gt;
&lt;td&gt;18.06%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;60,302&lt;/td&gt;
&lt;td&gt;56.27%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;2-9&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;21,361&lt;/td&gt;
&lt;td&gt;19.93%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;10-99&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5,164&lt;/td&gt;
&lt;td&gt;4.82%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;100-999&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;838&lt;/td&gt;
&lt;td&gt;0.78%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;1,000+&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;139&lt;/td&gt;
&lt;td&gt;0.13%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Only &lt;code&gt;5.73%&lt;/code&gt; of Actors reached 10 or more 30-day users, and &lt;code&gt;0.91%&lt;/code&gt; reached 100 or more.&lt;/p&gt;

&lt;p&gt;A &lt;code&gt;totalUsers30Days&lt;/code&gt; of &lt;code&gt;1&lt;/code&gt; needs care. Apify runs automated daily health checks on Store Actors with prefilled inputs. In the November 4 data, Actors with &lt;code&gt;0&lt;/code&gt; or &lt;code&gt;1&lt;/code&gt; 30-day users had a median of &lt;code&gt;28&lt;/code&gt; and &lt;code&gt;27&lt;/code&gt; runs per 30 days, matching one automated check per day. The public data cannot distinguish an outside user from the author or from that check.&lt;/p&gt;

&lt;p&gt;At the author level, concentration is even sharper:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The top &lt;code&gt;1.16%&lt;/code&gt; of authors (&lt;code&gt;101&lt;/code&gt; of &lt;code&gt;8,714&lt;/code&gt;) accounted for &lt;code&gt;80.12%&lt;/code&gt; of all 30-day Actor-user pairs (&lt;code&gt;1,033,771&lt;/code&gt; out of &lt;code&gt;1,290,301&lt;/code&gt;). The author Gini coefficient was &lt;code&gt;0.969&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Excluding 6 official Apify and staff accounts (&lt;code&gt;188&lt;/code&gt; Actors, &lt;code&gt;28.8%&lt;/code&gt; of total 30-day users), the top 20 independent authors held &lt;code&gt;48.0%&lt;/code&gt; of remaining 30-day users, and the top 100 held &lt;code&gt;72.4%&lt;/code&gt; (November 6 analysis of the November 4 snapshot).&lt;/li&gt;
&lt;li&gt;Publishing volume alone does not put an author in the top tier. Middle-tier authors (&lt;code&gt;478&lt;/code&gt; accounts holding the next &lt;code&gt;15%&lt;/code&gt; of users) published a median of &lt;code&gt;50&lt;/code&gt; Actors compared with &lt;code&gt;43&lt;/code&gt; for top-tier authors, yet had a median of &lt;code&gt;248&lt;/code&gt; 30-day users per author compared with &lt;code&gt;3,040&lt;/code&gt; in the top tier (&lt;code&gt;14.89%&lt;/code&gt; of total users vs. &lt;code&gt;80.12%&lt;/code&gt;). Meanwhile, the top 20 independent authors had a median of &lt;code&gt;22&lt;/code&gt; Actors, &lt;code&gt;21&lt;/code&gt; of them with 30-day users.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Category supply vs. demand
&lt;/h2&gt;

&lt;p&gt;Because an Actor can belong to multiple categories, comparing each category's share of total users against its share of Actors (&lt;code&gt;user share / Actor share&lt;/code&gt;) shows where supply is crowded relative to demand.&lt;/p&gt;

&lt;p&gt;In the November 4 full-catalog data (13 of 25 categories, chosen by size and ratio):&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Category&lt;/th&gt;
&lt;th&gt;Actors&lt;/th&gt;
&lt;th&gt;30-day users&lt;/th&gt;
&lt;th&gt;Demand / supply ratio&lt;/th&gt;
&lt;th&gt;Actors with 10+ users&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SOCIAL_MEDIA&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;14,962&lt;/td&gt;
&lt;td&gt;701,552&lt;/td&gt;
&lt;td&gt;3.89x&lt;/td&gt;
&lt;td&gt;15.60%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;OPEN_SOURCE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;1,167&lt;/td&gt;
&lt;td&gt;45,753&lt;/td&gt;
&lt;td&gt;3.26x&lt;/td&gt;
&lt;td&gt;4.03%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;VIDEOS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;5,148&lt;/td&gt;
&lt;td&gt;188,177&lt;/td&gt;
&lt;td&gt;3.04x&lt;/td&gt;
&lt;td&gt;12.26%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;TRAVEL&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;3,750&lt;/td&gt;
&lt;td&gt;78,280&lt;/td&gt;
&lt;td&gt;1.73x&lt;/td&gt;
&lt;td&gt;6.05%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;LEAD_GENERATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;33,448&lt;/td&gt;
&lt;td&gt;538,554&lt;/td&gt;
&lt;td&gt;1.34x&lt;/td&gt;
&lt;td&gt;7.79%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AI&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;13,775&lt;/td&gt;
&lt;td&gt;189,574&lt;/td&gt;
&lt;td&gt;1.14x&lt;/td&gt;
&lt;td&gt;5.83%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;SEO_TOOLS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;7,587&lt;/td&gt;
&lt;td&gt;81,103&lt;/td&gt;
&lt;td&gt;0.89x&lt;/td&gt;
&lt;td&gt;6.81%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;JOBS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;9,492&lt;/td&gt;
&lt;td&gt;99,936&lt;/td&gt;
&lt;td&gt;0.87x&lt;/td&gt;
&lt;td&gt;6.39%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;AUTOMATION&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;37,609&lt;/td&gt;
&lt;td&gt;372,447&lt;/td&gt;
&lt;td&gt;0.82x&lt;/td&gt;
&lt;td&gt;6.41%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ECOMMERCE&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;17,915&lt;/td&gt;
&lt;td&gt;131,731&lt;/td&gt;
&lt;td&gt;0.61x&lt;/td&gt;
&lt;td&gt;5.97%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;DEVELOPER_TOOLS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;29,880&lt;/td&gt;
&lt;td&gt;192,990&lt;/td&gt;
&lt;td&gt;0.54x&lt;/td&gt;
&lt;td&gt;4.73%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;BUSINESS&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;12,525&lt;/td&gt;
&lt;td&gt;24,047&lt;/td&gt;
&lt;td&gt;0.16x&lt;/td&gt;
&lt;td&gt;2.25%&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;em&gt;(no category)&lt;/em&gt;&lt;/td&gt;
&lt;td&gt;12,957&lt;/td&gt;
&lt;td&gt;24,912&lt;/td&gt;
&lt;td&gt;0.16x&lt;/td&gt;
&lt;td&gt;1.64%&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Our November 13 sample uses cumulative &lt;code&gt;totalUsers&lt;/code&gt; rather than 30-day users, and over-represents popular Actors, so read it as a cross-check. In that sample the four highest-ratio categories of the full data are also above parity: &lt;code&gt;SOCIAL_MEDIA&lt;/code&gt; &lt;code&gt;2.30x&lt;/code&gt; on &lt;code&gt;3,557&lt;/code&gt; Actors, &lt;code&gt;OPEN_SOURCE&lt;/code&gt; &lt;code&gt;10.05x&lt;/code&gt; on &lt;code&gt;65&lt;/code&gt;, &lt;code&gt;VIDEOS&lt;/code&gt; &lt;code&gt;2.50x&lt;/code&gt; on &lt;code&gt;1,000&lt;/code&gt;, and &lt;code&gt;TRAVEL&lt;/code&gt; &lt;code&gt;2.11x&lt;/code&gt; on &lt;code&gt;565&lt;/code&gt; (the last two sit outside the top 12 by Actor count plotted in Figure 2). Uncategorized listings (&lt;code&gt;0.03x&lt;/code&gt;) and &lt;code&gt;BUSINESS&lt;/code&gt; (&lt;code&gt;0.07x&lt;/code&gt;) sit near the bottom. Leaving categories blank goes with low usage: only &lt;code&gt;1.64%&lt;/code&gt; of uncategorized Actors in the full catalog reached 10+ users. After November 15 the category values themselves change (see the list below), so category counts before and after the switch are not directly comparable.&lt;/p&gt;

&lt;h2&gt;
  
  
  What differs in a matched cohort of recent launches
&lt;/h2&gt;

&lt;p&gt;Actors created between August 12 and October 11, 2026, split into &lt;code&gt;701&lt;/code&gt; that reached at least &lt;code&gt;20&lt;/code&gt; 30-day users and &lt;code&gt;1,326&lt;/code&gt; matched controls with &lt;code&gt;3&lt;/code&gt; or fewer users (same primary function and creation month). One large difference was the audience of the author's other Actors: measured on November 10, their combined 30-day users had a median of &lt;code&gt;1,370&lt;/code&gt; for the winners' authors and &lt;code&gt;180&lt;/code&gt; for the controls' authors, while the winners' authors listed a median of &lt;code&gt;92&lt;/code&gt; Actors against &lt;code&gt;113&lt;/code&gt;. We report this as a correlation; the audience was measured after launch, so it may partly follow from the winners.&lt;/p&gt;

&lt;h2&gt;
  
  
  What breaks on November 15, 2026 in &lt;code&gt;GET /v2/store&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;If you run scripts against &lt;code&gt;https://api.apify.com/v2/store&lt;/code&gt; (or &lt;code&gt;apify-client&lt;/code&gt;), Apify's October 30, 2026 changelog says the endpoint moves to a new search backend on November 15, 2026. Most of these changes return &lt;code&gt;200 OK&lt;/code&gt;, so loops can break without an error:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Passing &lt;code&gt;search&lt;/code&gt; caps results at 100 items on one page. &lt;code&gt;limit&lt;/code&gt; drops from &lt;code&gt;1,000&lt;/code&gt; to &lt;code&gt;100&lt;/code&gt;, &lt;code&gt;offset&lt;/code&gt; is ignored without an error, and there is no second page. &lt;code&gt;total&lt;/code&gt; and &lt;code&gt;count&lt;/code&gt; also change meaning when &lt;code&gt;search&lt;/code&gt; is present: both equal the number of items returned (&lt;code&gt;&amp;lt;= 100&lt;/code&gt;), not total matches. Any loop written as &lt;code&gt;while offset &amp;lt; total:&lt;/code&gt; stops after one page.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;sortBy&lt;/code&gt; is ignored on all calls. Passing &lt;code&gt;sortBy=popularity&lt;/code&gt; or &lt;code&gt;sortBy=newest&lt;/code&gt; returns &lt;code&gt;200 OK&lt;/code&gt; without error, yet results return in relevance order (with &lt;code&gt;search&lt;/code&gt;) or default Store order (without &lt;code&gt;search&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Top-level rating and bookmark fields disappear. &lt;code&gt;bookmarkCount&lt;/code&gt;, &lt;code&gt;actorReviewCount&lt;/code&gt;, and &lt;code&gt;actorReviewRating&lt;/code&gt; are removed from the top level of each item. Ratings remain under &lt;code&gt;stats.actorReviewRating&lt;/code&gt; and &lt;code&gt;stats.actorReviewCount&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Build and 30-day run histograms are removed from &lt;code&gt;stats&lt;/code&gt;. &lt;code&gt;stats.bookmarkCount&lt;/code&gt;, &lt;code&gt;stats.publicActorRunStats30Days&lt;/code&gt;, &lt;code&gt;stats.totalBuilds&lt;/code&gt;, &lt;code&gt;stats.totalMetamorphs&lt;/code&gt;, and &lt;code&gt;stats.lastRunStartedAt&lt;/code&gt; are dropped.&lt;/li&gt;
&lt;li&gt;User-window fields become optional. &lt;code&gt;stats.totalRuns&lt;/code&gt;, &lt;code&gt;stats.totalUsers7Days&lt;/code&gt;, &lt;code&gt;stats.totalUsers30Days&lt;/code&gt;, and &lt;code&gt;stats.totalUsers90Days&lt;/code&gt; may be absent, while &lt;code&gt;stats.totalUsers&lt;/code&gt; stays. Several item fields, including &lt;code&gt;userFullName&lt;/code&gt;, &lt;code&gt;notice&lt;/code&gt;, &lt;code&gt;badge&lt;/code&gt; and &lt;code&gt;isWhiteListedForAgenticPayments&lt;/code&gt;, may also be absent, and &lt;code&gt;currentPricingInfo&lt;/code&gt; keeps only &lt;code&gt;pricingModel&lt;/code&gt; plus event prices.&lt;/li&gt;
&lt;li&gt;Category values change. &lt;code&gt;category&lt;/code&gt; takes comma-separated category IDs (an Actor must match all of them), categories are assigned automatically from a larger list, and an unknown value returns &lt;code&gt;400&lt;/code&gt;. Old keys such as &lt;code&gt;SOCIAL_MEDIA&lt;/code&gt; still work, but the same key can return different Actors, so category counts before and after November 15 are not directly comparable.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;As of November 13, 2026 (&lt;code&gt;02:08 UTC&lt;/code&gt;), &lt;code&gt;GET /v2/store&lt;/code&gt; still returned the old schema: &lt;code&gt;isVerified&lt;/code&gt; and &lt;code&gt;readmeSummary&lt;/code&gt; were absent, and &lt;code&gt;stats.totalUsers30Days&lt;/code&gt; was present on all sampled items.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to keep counting after November 15
&lt;/h2&gt;

&lt;p&gt;Listings without &lt;code&gt;search&lt;/code&gt; keep &lt;code&gt;limit&lt;/code&gt;/&lt;code&gt;offset&lt;/code&gt; paging and accurate &lt;code&gt;total&lt;/code&gt; counts. In our own tests before the switch, a single query stopped returning items past offset &lt;code&gt;15,000&lt;/code&gt;; we have not confirmed that window on the new backend, so keep each query below it. To keep tracking the Store:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Drop &lt;code&gt;search&lt;/code&gt; and &lt;code&gt;sortBy&lt;/code&gt; from catalog crawls. Use &lt;code&gt;category&lt;/code&gt;, &lt;code&gt;username&lt;/code&gt;, or &lt;code&gt;pricingModel&lt;/code&gt; filters to slice a catalog under the offset window, and sort locally. After November 15 category IDs and assignments change, so category-based slices are not comparable across the switch.&lt;/li&gt;
&lt;li&gt;Read ratings from &lt;code&gt;stats.actorReviewRating&lt;/code&gt; and &lt;code&gt;stats.actorReviewCount&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Base cross-switch series on &lt;code&gt;stats.totalUsers&lt;/code&gt; (or fall back to it when &lt;code&gt;stats.totalUsers30Days&lt;/code&gt; is absent), and avoid indexing directly into &lt;code&gt;publicActorRunStats30Days&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is the paging core from our reproducible script (&lt;code&gt;analyze_store.py&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;seen_ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;max_items&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;15000&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;batch_limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;min&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_items&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;15000&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"limit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;batch_limit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"offset"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="s2"&gt;"includeUnrunnableActors"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;# full catalog count&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;session&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https://api.apify.com/v2/store"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raise_for_status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;batch&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"items"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;aid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;aid&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;aid&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;seen_ids&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;seen_ids&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;aid&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;offset&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;batch&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;batch_limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;0.6&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c1"&gt;# stay under 2 req/s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The full script also retries &lt;code&gt;429&lt;/code&gt; and &lt;code&gt;5xx&lt;/code&gt; responses and enforces &lt;code&gt;--delay&lt;/code&gt; between requests; this excerpt is the paging core.&lt;/p&gt;

&lt;p&gt;Running this on November 13 with &lt;code&gt;--max-items 15000&lt;/code&gt; made &lt;code&gt;15&lt;/code&gt; requests, reported &lt;code&gt;catalog_total_reported = 119,113&lt;/code&gt;, and returned &lt;code&gt;13,990&lt;/code&gt; distinct Actors across &lt;code&gt;2,082&lt;/code&gt; authors. &lt;code&gt;1,010&lt;/code&gt; rows repeated an Actor already seen, most likely because the Store order shifted while we paged; the same shift can also skip Actors, so the 15 pages held &lt;code&gt;13,990&lt;/code&gt; distinct Actors rather than a clean top &lt;code&gt;15,000&lt;/code&gt;. In that slice, &lt;code&gt;21&lt;/code&gt; authors (&lt;code&gt;1%&lt;/code&gt;) held &lt;code&gt;67.48%&lt;/code&gt; of cumulative &lt;code&gt;totalUsers&lt;/code&gt; (&lt;code&gt;10,713,587&lt;/code&gt;), and &lt;code&gt;95.39%&lt;/code&gt; (&lt;code&gt;13,345&lt;/code&gt;) of sampled Actors were priced per event versus &lt;code&gt;4.61%&lt;/code&gt; (&lt;code&gt;645&lt;/code&gt;) free.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe5n4sqeqxpa0rhf3b4w2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fe5n4sqeqxpa0rhf3b4w2.png" alt="Apify Store user distribution and author concentration, cumulative totalUsers sample of 13,990 Actors, November 13, 2026" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1: Not the full catalog: cumulative-user buckets and cumulative author concentration curve from a 13,990-Actor public API sample collected on November 13, 2026 (&lt;code&gt;02:08 UTC&lt;/code&gt;, catalog total &lt;code&gt;119,113&lt;/code&gt;). Source: &lt;code&gt;analyze_store.py&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flvm3cfuwgu9qfno6i9o3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Flvm3cfuwgu9qfno6i9o3.png" alt="Category demand to supply ratio, top 12 categories by count, November 13, 2026" width="800" height="438"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2: Demand-to-supply ratio across the top 12 categories by count in the November 13, 2026 sample (&lt;code&gt;n = 13,990&lt;/code&gt;). Source: &lt;code&gt;out/category_summary.csv&lt;/code&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Scope and limitations
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Sample bias in the 15-page run: in our tests, &lt;code&gt;GET /v2/store&lt;/code&gt; returned at most &lt;code&gt;15,000&lt;/code&gt; items per query in Store order, and the quick &lt;code&gt;repro&lt;/code&gt; script stops at that window, so it over-represents active Actors: &lt;code&gt;32.69%&lt;/code&gt; of sampled Actors had &lt;code&gt;10&lt;/code&gt; or more 30-day users, against &lt;code&gt;5.73%&lt;/code&gt; in the full &lt;code&gt;107,156&lt;/code&gt;-Actor harvest from November 4. To cover more of the catalog after November 15, slice the crawl with the filters the changelog recommends (category, username, pricingModel) and keep each slice under the window.&lt;/li&gt;
&lt;li&gt;Actor-user sums: author totals sum per-Actor user counts, so one developer running two Actors by the same author is counted twice.&lt;/li&gt;
&lt;li&gt;Correlations only: the 30-to-90-day cohort numbers are observational comparisons.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;The full reproducible Python script, sample CSVs, and charts are at &lt;a href="https://github.com/kizukidata/apify-store-analysis" rel="noopener noreferrer"&gt;github.com/kizukidata/apify-store-analysis&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We publish Actors on the Apify Store as Kizuki, so we are not a neutral party.&lt;/p&gt;

&lt;h3&gt;
  
  
  Sources
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Full-catalog snapshot (&lt;code&gt;107,156&lt;/code&gt; Actors, &lt;code&gt;8,714&lt;/code&gt; authors): collected between &lt;code&gt;2026-11-03&lt;/code&gt; and &lt;code&gt;2026-11-04 UTC&lt;/code&gt; from public &lt;code&gt;GET /v2/store&lt;/code&gt;, &lt;code&gt;/v2/users/{u}&lt;/code&gt;, and &lt;code&gt;/v2/acts/{id}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Author ranking (excluding &lt;code&gt;6&lt;/code&gt; official/staff accounts): computed &lt;code&gt;2026-11-06&lt;/code&gt; from the &lt;code&gt;2026-11-04&lt;/code&gt; snapshot.&lt;/li&gt;
&lt;li&gt;Early-traction cohort (&lt;code&gt;701&lt;/code&gt; vs. &lt;code&gt;1,326&lt;/code&gt; Actors created &lt;code&gt;2026-08-12&lt;/code&gt; to &lt;code&gt;2026-10-11&lt;/code&gt;): collected &lt;code&gt;2026-11-10 UTC&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Live Store sample (&lt;code&gt;13,990&lt;/code&gt; Actors, catalog total &lt;code&gt;119,113&lt;/code&gt;): collected &lt;code&gt;2026-11-13 02:08 UTC&lt;/code&gt; via &lt;code&gt;analyze_store.py&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;API migration details: Apify Store API changelog (&lt;code&gt;2026-10-30&lt;/code&gt;), &lt;a href="https://apify.com/change-log/apify-store-api" rel="noopener noreferrer"&gt;apify.com/change-log/apify-store-api&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Disclosure: This article was created with the help of AI; we checked the data, code, and links against the sources above.&lt;/p&gt;

</description>
      <category>python</category>
      <category>api</category>
      <category>webscraping</category>
      <category>apify</category>
    </item>
  </channel>
</rss>
