While the IsReadOnly still cannot be set at creation because error Field is not writeable persists, the closest we can get to set the ContentNote to read-only is by setting the ShareType to V on the ContentDocumentLink that links the note to a record.
// First create and insert the note ContentNote note = new ContentNote(); note.Title = 'My Note'; note.Content = Blob.valueOf('This is the note text'); insert note; // Then create the ContentDocumentLink with ShareType = 'V' for viewer permission ContentDocumentLink cdl = new ContentDocumentLink(); cdl.ContentDocumentId = note.Id; cdl.LinkedEntityId = '<recordId>'; // The ID of the record you're sharing to cdl.ShareType = 'V'; // 'V' for Viewer permission makes it read-only cdl.Visibility = 'AllUsers'; // or whatever visibility you need insert cdl;
One thing that comes up after the above is that another user indeed sees the note as read-only and there's a text that clearly indicates this:

If we write a simple LWC to query and display the IsReadOnly field, viewing the information as another user shows that IsReadOnly = true
ContentDocumentLink documentation